Spring Framework는 container 내부의 bean의 행동을 변화시길 수 있는 다양한 callback interface를 제공한다.
org.springframework.beans.factory.InitializingBean
interface를 구현하면 bean에 필요한 모든 property를 설정한 후, 초기화 작업을 수행한다. InitializingBean
interface는 다음 메소드를 명시하고 있다.
void afterPropertiesSet() throws Exception;
일반적으로, InitializingBean
interface의 사용을 권장하지 않는다. 왜냐하면 code가 불필요하게 Spring과 결합되기(couple) 때문이다. 대안으로, bean 정의는 초기화 메소드를
지정할 수 있다. XML 기반 설정의 경우, 'init-method
' attribute를 사용한다.
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
public class ExampleBean { public void init() { // do some initialization work } }
위 예제는 아래 예제와 같다.
<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
public class AnotherExampleBean implements InitializingBean { public void afterPropertiesSet() { // do some initialization work } }
org.springframework.beans.factory.DisposableBean
interface를 구현하면, container가 파괴될 때 bean이 callback를 받을 수 있다. DisposableBean
interface는 다음 메소드를 명시하고 있다.
void destroy() throws Exception;
일반적으로, DisposableBean
interface의 사용을 권장하지 않는다. 왜냐하면 code가 불필요하게 Spring과 결합되기(couple) 때문이다. 대안으로, bean 정의는 초기화 메소드를
지정할 수 있다. XML 기반 설정의 경우, 'destroy-method
' attribute를 사용한다.
<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>
public class ExampleBean { public void cleanup() { // do some destruction work (like releasing pooled connections) } }
위 예제는 아래 예제와 같다.
<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
public class AnotherExampleBean implements DisposableBean { public void destroy() { // do some destruction work (like releasing pooled connections) } }
Spring container는 모든 bean에 대해서 같은 이름의 초기화 및 파괴 메소드를 지정할 수 있다.
public class DefaultBlogService implements BlogService { private BlogDao blogDao; public void setBlogDao(BlogDao blogDao) { this.blogDao = blogDao; } // this is (unsurprisingly) the initialization callback method public void init() { if (this.blogDao == null) { throw new IllegalStateException("The [blogDao] property must be set."); } } }
<beans default-init-method="init"> <bean id="blogService" class="com.foo.DefaultBlogService"> <property name="blogDao" ref="blogDao" /> </bean> </beans>
<beans/>
element의 'default-init-method
' attribute를 이용하여 기본 객체화 callback 메소드를 지정할 수 있다. 파괴 callback 메소드의 경우 'default-destroy-method
' attribute를 이용하여 지정할 수 있다.
<bean/>
element에 'init-method
', 'destroy-method
' attribute가 정의되어 있는 경우, 기본값은 무시된다.
Spring Framework에서는 3가지 방식의 생명주기 메커니즘이 존재한다: InitialzingBean
과 DisposableBean
interface; 맞춤 init()
과 destroy()
메소드; 그리고 @PostConstruct and @PreDestroy annotations
만약 서로 다른 생명주기 메커니즘을 같이 사용할 경우, 개발자는 적용되는 순서를 알고 있어야 한다. 객체화 메소드의 순서는 다음과 같다.
InitializingBean
callback interface에 정의된 afterPropertiesSet()
init()
메소드파괴 메소드의 호출 순서는 다음과 같다.
DisposableBean
callback interface에 정의된 destroy()
destroy()
메소드
org.springframework.beans.factory.BeanFactoryAware
interface를 구현한 class는 자신을 생성한 BeanFactory
를 참조할 수 있다.
public interface BeanFactoryAware { void setBeanFactory(BeanFactory beanFactory) throws BeansException; }
BeanFactoryWare
interface를 사용하면, 자신을 생성한 BeanFactory
를 알 수 있고, 프로그램적으로 다른 bean을 검색할 수 있다. 하지만 이 방법은 Spring과의 결합을 발생시키고, Inversion of Control 스타일에도 맞지 않으므로 피하는 것이 좋다.
대안으로는 org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean
을 사용할 수 있다.
ObjectFactoryCreatingFactoryBean
은 FactoryBean
을 구현한 것으로 bean을 찾아주는 객체를 참조할 수 있다. ObjectFactoryCreatingFactoryBean
은 스스로 BeanFactoryAware
interface를 구현하고 있다.
package x.y; public class NewsFeed { private String news; public void setNews(String news) { this.news = news; } public String getNews() { return this.toString() + ": '" + news + "'"; } }
package x.y; import org.springframework.beans.factory.ObjectFactory; public class NewsFeedManager { private ObjectFactory factory; public void setFactory(ObjectFactory factory) { this.factory = factory; } public void printNews() { // here is where the lookup is performed; note that there is no // need to hard code the name of the bean that is being looked up... NewsFeed news = (NewsFeed) factory.getObject(); System.out.println(news.getNews()); } }
아래 설정은 ObjectFactoryCreatingFactoryBean
방식을 사용하여 위 두 class를 엮어주는 예제이다.
<beans> <bean id="newsFeedManager" class="x.y.NewsFeedManager"> <property name="factory"> <bean class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean"> <property name="targetBeanName"> <idref local="newsFeed" /> </property> </bean> </property> </bean> <bean id="newsFeed" class="x.y.NewsFeed" scope="prototype"> <property name="news" value="... that's fit to print!" /> </bean> </beans>
org.springframework.beans.factory.BeanNameAware
interface를 구현한 bean은 container내에서의 name을 알 수 있다.