스프링 컨테이너는 빈을 관리한다. 싱글턴 레지스트리 기능을 제공하거나 의존 주입 등을 하는 것 외에도 빈 객체의 생명주기 역시 관리한다. 컨테이너가 초기화될 때 빈 객체를 생성하여 등록, 의존성 주입을 하고 컨테이너가 종료될 시점에 빈 객체 역시 소멸시킨다.
스프링 빈 이벤트 생명주기
스프링컨테이너 생성 -> 스프링 빈 생성 -> 의존관계 주입 -> 초기화 콜백 -> 사용 -> 소멸전 콜백 -> 스프링 종료
위의 빈 생명주기에서 보듯이 스프링은 빈의 의존관계 주입이 완료되면 콜백 메서드를 통해 초기화 시점을 알려주는 다양한 기능을 제공해준다. 마찬가지로 스프링 컨테이너가 소멸 전에도 소멸 콜백을 제공한다.
객체의 생성과 초기화를 분리하자.
생성자의 책임은 파라미터를 받고 메모리를 할당하여 객체를 생성하는 것이다. 반면 초기화는 이렇게 생성된 객체의 값을 활용하여 무거운 동작을 수행한다. 따라서 생성자 안에서 초기화 작업을 함께 진행하는 것 보다는 초기화 부분을 나누어 관리하는 것이 유지보수 관점에서 좋다.
빈 생명주기를 조금 더 디테일하게 들여다 보면 아래의 그림과 같다.
스프링은 인터페이스, 설정 정보 활용, @PostConstruct, @PreDestroy 어노테이션 사용 등 크게 3가지 방법으로 빈 생명주기 콜백을 지원한다.
InitializingBean 인터페이스를 구현 후 afterPropertiesSet() 메서드에 코드를 작성한다.
@Component
class MySpringBean implements InitializingBean {
@Override
public void afterPropertiesSet() {
//...
}
}
이와 유사하게 DisposableBean을 구현하여 destroy() 메서드를 오버라이드 하면 소멸 전에 해당 콜백 메서드를 호출한다.
@Component
class MySpringBean implements DisposableBean {
@Override
public void destroy() {
//...
}
}
@Bean(initMethod = "init", destroyMethod = "close")
와 같이 설정 정보에 메서드를 지정가능하다.
@Configuration
class MySpringConfiguration {
@Bean(initMethod = "onInitialize", destroyMethod = "onDestroy")
public MySpringBean mySpringBean() {
return new MySpringBean();
}
}
인터페이스 사용과 달리 메서드 이름을 자유롭게 지정할 수 있으며 스프링 코드에 의존하지도 않게 된다. 또한 설정 정보를 이용하므로 코드 변경이 불가한 외부 라이브러리에도 초기화 및 종료 메서드를 적용할 수 있다.
참고로 빈에 close() 혹은 shutdown() 메서드가 있다면 자동으로 소멸 전에 해당 메서드를 호출한다. 만약 이러한 추론 기능을 사용하기 싫다면 아래와 같이 세팅해주면된다.
@Configuration
class MySpringConfiguration {
@Bean(destroyMethod = "")
public MySpringBean mySpringBean() {
return new MySpringBean();
}
}
pre-initialization 페이즈와 destroy 페이즈에 이 어노테이션들을 사용할 수 있다.
@Component
class MySpringBean {
@PostConstruct
public void postConstruct() {
//...
}
@PreDestroy
public void preDestroy() {
//...
}
}
이 방법이 최신 스프링에서 가장 권장하는 방법이다. 스프링 종속적인 기술이 아닌 JSR-250 자바 표준에 속한 어노테이션이므로 스프링 의존적이지 않게 된다.
외부 라이브러리에는 적용할 수 없으므로 만약 외부 라이브러리에 콜백을 사용하려면 @Bean 어트리뷰트 기능을 함께 사용해야 한다.
인프런 스프링 핵심원리 기본편
https://haruhiism.tistory.com/186
https://reflectoring.io/spring-bean-lifecycle/