Customizing the nature of a bean

개요

설명

Lifecycle callbacks

Spring Framework는 container 내부의 bean의 행동을 변화시길 수 있는 다양한 callback interface를 제공한다.

객체화 callbacks(Initialization callbacks)

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
    }
}

파괴 callbacks(Destruction callbacks)

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)
    }
}

기본 객체화 및 파괴 메소드(Default initialization & destroy methods)

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 2.5에서는 3가지 방식의 생명주기 메커니즘이 존재한다: InitialzingBeanDisposableBean interface; 맞춤 init()destroy() 메소드; 그리고 @PostConstruct and @PreDestroy annotations

만약 서로 다른 생명주기 메커니즘을 같이 사용할 경우, 개발자는 적용되는 순서를 알고 있어야 한다. 객체화 메소드의 순서는 다음과 같다.

  1. @PostConstruct annotation이 있는 메소드
  2. InitializingBean callback interface에 정의된 afterPropertiesSet()
  3. 맞춤 init() 메소드

파괴 메소드의 호출 순서는 다음과 같다.

  1. @PreDestroy annotation이 있는 메소드
  2. DisposableBean callback interface에 정의된 destroy()
  3. 맞춤 destroy() 메소드

Knowing who you are

BeanFactoryAware

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을 사용할 수 있다.

ObjectFactoryCreatingFactoryBeanFactoryBean을 구현한 것으로 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>

BeanNameAware

org.springframework.beans.factory.BeanNameAware interface를 구현한 bean은 container내에서의 name을 알 수 있다.

참고자료

 
egovframework/rte2/fdl/ioc_container/customizing_the_nature_of_a_bean.txt · 마지막 수정: 2023/12/21 05:21 (외부 편집기)
 
이 위키의 내용은 다음의 라이센스에 따릅니다 :CC Attribution-Noncommercial-Share Alike 3.0 Unported
전자정부 표준프레임워크 라이센스(바로가기)

전자정부 표준프레임워크 활용의 안정성 보장을 위해 위험성을 지속적으로 모니터링하고 있으나, 오픈소스의 특성상 문제가 발생할 수 있습니다.
전자정부 표준프레임워크는 Apache 2.0 라이선스를 따르고 있는 오픈소스 프로그램입니다. Apache 2.0 라이선스에 따라 표준프레임워크를 활용하여 발생된 업무중단, 컴퓨터 고장 또는 오동작으로 인한 손해 등에 대해서 책임이 없습니다.
Recent changes RSS feed CC Attribution-Noncommercial-Share Alike 3.0 Unported Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki