스프링 Bean 은 다음과 같은 라이프사이클
- (Bean) 객체 생성
- 의존관계 주입
- 스프링 컨테이너 생성 (ApplicationContext)
- 스프링 Bean 생성/등록
- 의존관계 주입 (DI)
- 초기화 콜백 : 빈 생성 / DI 이후 호출
- 사용 (개발자 코드 동작)
- 소멸(전) 콜백 : 빈 소멸 전 호출
- 스프링(스프링 컨테이너) 종료
생성자에서 하면 되는 것을, 왜(굳이) 초기화 콜백 사용??
-> (권장!!) 객체의 생성 / 초기화 분리한다.
- 책임 / 역할 분리
생성자
: 필수 정보 / 메모리 할당 등 ‘생성’ 에 중점을 둔다.초기화
: 생성 이후에 로직에 필요한 값 전에 ‘초기화’ 에 중점을 둔다.
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() {
...
}
}