빈 생명 주기

빈 생명 주기

스프링 Bean 은 다음과 같은 라이프사이클

  1. (Bean) 객체 생성
  2. 의존관계 주입

  1. 스프링 컨테이너 생성 (ApplicationContext)
  2. 스프링 Bean 생성/등록
  3. 의존관계 주입 (DI)
  4. 초기화 콜백 : 빈 생성 / DI 이후 호출
  5. 사용 (개발자 코드 동작)
  6. 소멸(전) 콜백 : 빈 소멸 전 호출
  7. 스프링(스프링 컨테이너) 종료

생성자에서 하면 되는 것을, 왜(굳이) 초기화 콜백 사용??

-> (권장!!) 객체의 생성 / 초기화 분리한다.

  • 책임 / 역할 분리
    • 생성자 : 필수 정보 / 메모리 할당 등 ‘생성’ 에 중점을 둔다.
    • 초기화 : 생성 이후에 로직에 필요한 값 전에 ‘초기화’ 에 중점을 둔다.



3가지 방법으로 ‘빈 생명주기 콜백’ 을 지원 #

  • 인터페이스 : InitializingBean, DisposableBean
  • 설정 정보 : 초기화 메서드, 종료 메서드 지정
  • 애노테이션 : @PostConstruct, @PreDestroy

1. 인터페이스 : InitializingBean, DisposableBean #

스프링 초기 시절에 많이 사용되었고, 현재는 많이 사용되고 있지는 않는다고 함

  • 스프링 전용 인터페이스 : 스프링에 의존한다.
    • 애노테이션 등의 의존은 그렇다 쳐도, 코드 레벨의 의존은 조금 그렇다.
  • 초기화, 소멸 메서드 이름을 변경할 수 없음
  • 내가 작성한 코드가 아닌, (내가 고칠 수 없는)외부 코드/라이브러리에 적용할 수 없음
/**
 * Interface to be implemented by beans that need to react once all their properties have been set by a BeanFactory: 
 * e.g. to perform custom initialization, or merely to check that all mandatory properties have been set.
 *
 * An alternative to implementing InitializingBean is specifying a custom init method, 
 * for example in an XML bean definition. 
 *
 * For a list of all bean lifecycle methods, see the BeanFactory javadocs.
 */
public interface InitializingBean {

	/**
	 * Invoked by the containing BeanFactory after it has set all bean properties
	 * and satisfied BeanFactoryAware, ApplicationContextAware etc.
	 * This method allows the bean instance to perform validation of its overall
	 * configuration and final initialization when all bean properties have been set.
     *
	 * @throws Exception in the event of misconfiguration (such as failure to set an
	 * essential property) or if initialization fails for any other reason
	 */
	void afterPropertiesSet() throws Exception;

}

/**
 * Interface to be implemented by beans that want to release resources on destruction.
 * A BeanFactory will invoke the destroy method on individual destruction of a scoped bean. 
 *
 * An org.springframework.context.ApplicationContext is supposed to dispose all of its singletons on shutdown, driven by the application lifecycle.
 *
 * A Spring-managed bean may also implement Java's AutoCloseable interface for the same purpose. 
 * An alternative to implementing an interface is specifying a custom destroy method, for example in an XML bean definition.
 *
 * For a list of all bean lifecycle methods, see the BeanFactory javadocs.
 */
public interface DisposableBean {

	/**
	 * Invoked by the containing BeanFactory on destruction of a bean.
     *
	 * @throws Exception in case of shutdown errors. Exceptions will get logged
	 * but not rethrown to allow other beans to release their resources as well.
	 */
	void destroy() throws Exception;

}

2. 설정 정보 : 초기화 메서드, 종료 메서드 지정 #

  • 메서드 이름 : 자유롭게 지정
  • 스프링에 의존하지 않음
  • (설정 정보를 사용하기 때문에?)외부 라이브러리에도 적용 가능

@Bean 의 destroyMethod(default 값) : (inferred)

  • close, shutdown 등의 메서드가 있으면 자동으로 호출해준다. (추론)
  • 추론 기능 사용하기 싫으면 destroyMethod = "" 와 같이 설정
@Bean(initMethod = "myInit", destroyMethod = "myDestory")
public MyService myService() {
    return new MyService();
}

class MyService {
    void myInit() {
        ...
    }

    void myDestroy() {
        ...
    }
}

3. 애노테이션 : @PostConstruct, @PreDestroy #

가장 권장되는 방법

  • 스프링에서 권장
  • 패키지 : package javax.annotation;
    • 스프링에 종속 X
    • 자바 표준 (JSR)
  • 컴포넌트 스캔과 잘 어울림 (@Configuration, @Bean 사용이 아니니까)
  • 외부 라이브러리에 적용 X
    • 외부 라이브러리 적용이 필요하면 2번 방법(설정 정보 : 초기화 메서드, 종료 메서드 지정)을 이용
class MyService {
    @PostConstruct
    void myInit() {
        ...
    }

    @PreDestroy
    void myDestroy() {
        ...
    }
}