본문 바로가기

SpringFramework Core - I. IoC 컨테이너/6. Bean 커스터마이징하기

6.1.3. 기본적인 초기화/소멸 메소드들

원문: https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-lifecycle-default-init-destroy-methods

 

 

스프링에 특화된 InitializingBean과 DisposableBean 콜백 인터페이스를 사용하지 않고 초기화/소멸 메소드 콜백을 만들 때는 init(), initialize(), dispose() 등과 같은 이름의 메소드들을 작성하게 될 것이다. 이상적으로는, 그런 라이프사이클 메소드들의 이름이 프로젝트 전반에 걸쳐 규범화되어 다른 개발자들로 하여금 같은 메소드 이름을 사용하게하여 일관성을 지켜야한다.

 

스프링 컨테이너가 모든 bean에서 초기화와 소멸 콜백 메소드들을 찾아보도록 설정할 수 있다. 이 말은 bean 정의마다 init-method="init"이라는 설정을 하지 않고도, 애플리케이션의 클래스들을 작성할 수 있고 init() 이라는 초기화 콜백을 호출할 수 있다는 말이다. 스프링 IoC 컨테이너는 bean이 생성될 때 그 메소드를 호출한다. 이 기능은 초기화와 소멸 메소드 콜백들에 일관된 이름을 붙이도록 강제한다. 

 

여러분의 초기화 콜백 메소드의 이름이 init()이고, 소멸 콜백 메소드의 이름이 destroy()라고 가정해보자. 아마 예시 클래스처럼 생겼을 것이다.

public class DefaultBlogService implements BlogService {

    private BlogDao blogDao;
    
    public void setBlogDao(BlogDao blogDao) {
        this.blogDao = blogDao;
    }
    
    // 이것이 초기화 콜백 메소드이다.
    public void init() {
        if(this.blogDao == null) {
            throw new IllegalStateException("[blogDao] 프로퍼티가 세팅되어야 합니다.");
        }
    }
}

그러면 bean에서는 다음 예시처럼 클래스를 사용할 수 있을 것이다.

<beans default-init-method="init">
    <bean id="blogService" class="com.something.DefaultBlogService">
        <property name="blogDao" ref="blogDao" />
    </bean>
</beans>

상위의 <beans/> 요소에 있는 default-init-method 속성의 존재는, 스프링 IoC 컨테이너가 bean 클래스의 init 메소드를 초기화 콜백 메소드로서 인식할 수 있게끔 해준다. bean이 생성되고 조립될 때, bean 클래스가 해당 메소드를 가지고 있다면 적절한 시점에 호출될 것이다.

 

소멸 콜백 메소드들도 <beans/> 요소에 default-destroy-method를 사용함으로써 비슷하게 설정할 수 있다.

 

bean 클래스들이 이미 다양한 이름의 콜백 메소드들을 가지고 있다면, <bean/> 자체의 속성에 init-method와 destroy-method를 사용함으로써 메소드 이름의 기본값을 오버라이드할 수 있다.

 

스프링 컨테이너는 bean이 모든 의존성들을 제공받자마자 즉시 설정된 초기화 콜백이 호출되도록 보장한다. 그래서 초기화 콜백은 raw bean 참조라고 불린다. 이는 AOP 인터셉터 등이 아직 bean에 적용되지 않았음을 뜻한다. 먼저 대상 bean이 완전히 생성된 후에 AOP 프록시가 인터셉터 체인과 함께 적용된다. 만약 대상 bean과 프록시가 따로 정의됐다면 코드들이 프록시를 우회하여 raw한 대상 bean과 상호작용할 수 있을 것이다. 인터셉터들을 init 메소드에 적용시키는 것은 불일치를 가져올 것이다. 그렇게하면 대상 bean의 라이프사이클이 프록시 또는 인터셉터들과 결합되며, 코드들이 직접 raw한 대상 bean과 상호작용할 때 이상한 결과를 가져올 것이기 때문이다.