스프링 빈의 초기화 콜백, 소멸전 콜백에 대해서 공부했는데 사실 실제로 코드를 짜보면서 경험해본게 아니라서 완벽하게 언제 쓰이고 어떻게 응용할지 감이 전혀 오지 않지만 그래도 정리해 두려고 합니다.
결론부터 말하면
=> @PostConstruct, @PreDestory 어노테이션을 사용해서 빈 생성 이후 초기화와 , 빈 소멸 직전 정리를 하도록 합시다.
=> 코드를 고칠 수 없는 외부 라이브러리를 사용중일 경우에는
@Bean(initMethod ="", destoryMethod="") 를 사용하여 생성자와 소멸자를 명시해 주도록 합시다.
스프링 빈의 생명 주기는 대략적으로 다음과 같다고 합니다.
스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존관계 주입 -> 초기화 콜백 -> 사용(메소드 호출) -> 소멸전 콜백 -> 스프링 종료
스프링 빈을 사용하려면 스프링 빈이 생성되자마자 사용 가능한 것이 아니고 생성 이후 의존관계 주입이 끝나야지 해당 객체를 사용할 수 있을 것입니다. (Service 에 Repository가 주입되지 않고 메소드를 호출하면 NPE가 뜰 것이라는 것은 대충 생각해봐도 알 수 있다.)
그렇다면 의존관계 주입이 언제 끝나는지 알아야 그 이후로 메소드를 호출 하며 사용할 텐데, 이러한 부분은 스프링이 콜백 메서드를 통해 의존관계 주입이 완료되면 알려준다고 합니다. 또한 스프링 컨테이너가 종료되기 전에 소멸 콜백도 주기 때문에 안전하게 종료 작업을 진행할 수 있게 도와준다고 합니다.
💡 객체의 생성과 초기화를 분리합시다.
=> 객체생성은 생성자를 통해 필요한 매개변수들을 주입받고 객체를 생성하게 됩니다.
이후 초기화는 이렇게 생성된 값들을 활용해서 외부 커넥션을 연결하는 등 무거운 작업을 하는 경우가 많기에 객체의 생성자 내부에서는 입력받은 값을 저장하거나, 간단하게 내부 값들을 변경하는 등의 단순한 경우에는 생성자에서 한번에 처리해도 괜찮습니다. 그러나 초기화가 오래걸리고 무거운 작업이라면 생성 이후 따로 분리하여 처리하는 방법이 유지보수 관점에서 더 좋다고 합니다.
스프링은 3가지 방법으로 빈 생명주기 콜백을 지원한다고 합니다.
- 인터페이스(InitiallizingBean, DisposableBean)
- @Bean(initMethod, DestroyMethod)
- @PostConstruct, @PreDestory
하나씩 살펴 봅시다.
사진과 같이 두 인터페이스의 메소드를 오버라이드 해서 구현한다면 생성, 의존관계 주입 후 afterPropertiesSet() 메소드가 호출되고, 스프링 빈이 소멸 직전 destory() 메소드가 호출 됩니다.
💡 이 방법은 잘 사용하지 않습니다.
@Bean의 설정 정보에 초기화 메소드와 소멸 메소드를 지정할 수 있습니다.
초기화 메소드로 init()을, 소멸 메소드로 close()를 지정한 예시입니다.
💡 destroyMethod 의 기본값 (inferred)
=> destroyMethod는 default 값으로 (inferred) 라는 특이한 것을 가지고 있습니다.
보통 종료 메소드의 이름이 close, shutdown 이라는 이름을 많이 가지기 때문에 이러한 메소드들을 추론해서 호출해 줍니다. 이러한 기능을 사용하고 싶지 않다면 destroyMethod="" 와 같이 빈 공백을 설정 정보로 전달하면 됩니다.
위 사진과 같이 초기화, 종료 메소드에 어노테이션 하나만 붙여주면 됩니다.