빈 생명주기 콜백 시작
데이터베이스 커넥션 풀(관계형 데이터베이스 할 때 미리 서버랑 db를 연결한다.) 또는 애플리케이션 시작 시점에 연결을 미리 해두고 종료시점에 모두 종료하는 경우 이를 위한 초기화작업과 종료 작업을 어떻게 할지 알아보자!
여기서 초기화작업이란?
단순히 객체를 생성하는게 아니라, 그 객체가 동작까지 하는 것을 말한다.
public class NetworkClient {
private String url;
public NetworkClient() {
System.out.println("생성자 호출, url = " + url); connect();
call("초기화 연결 메시지");
}
public void setUrl(String url) {
this.url = url;
}
//서비스 시작시 호출
public void connect() {
System.out.println("connect: " + url);
이런 식으로 생성되는 시점에는 url이 null인데, 생성자에서 바로 connect를 호출한다면?
url을 세팅하려면 setUrl이 호출되어야하는데 그렇지 않은 상황 -> 오류발생
스프링 빈은 객체생성 -> 의존관계주입 이라는 라이프사이클을 가진다.
스프링빈은 의존관계주입이 모두 된 상태에서 사용할 수 있는 준비가 된다.
따라서 스프링은 의존관계 주입이 완료되면 스프링 빈에게 콜백메서드를 통해서 초기화 시점을 알려주고, 종료되기 전에 소멸콜백을 통해서 안전하게 종료작업을 할 수 있게 해준다.
스프링빈의 이벤트 라이프사이클
스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존관계 주입 -> 초기화 콜백 -> 사용 -> 소멸전 콜백 -> 스프링 종료
참고로, 객체의 생성과 초기화를 분리하는 것이 좋다.
객체의 생성자 안에는 무거운 초기화작업을 함께 하는 것이 아니라 정말 필요한 데이터만 세팅하고, 초기화하는 부분은 따로 두는 것이 유지보수에 더욱 효과적이다.
인터페이스 InitializingBean, DisposableBean
이 방법은 잘 사용하지 않는다.(수정 불가한 라이브러리를 가져와서 사용할 때 고칠 수 있는 방법이 없고 초기화, 소멸 메서드의 이름을 변경할 수 없어서)
public class NetworkClient implements InitializingBean, DisposableBean {
private String url;
public NetworkClient() {
System.out.println("생성자 호출, url = " + url);
}
public void setUrl(String url) {
this.url = url;
}
//서비스 시작시 호출
public void connect() {
System.out.println("connect: " + url);
}
public void call(String message) {
System.out.println("call: " + url + " message = " + message);
}
//서비스 종료시 호출
public void disConnect() {
System.out.println("close + " + url);
}
@Override
public void afterPropertiesSet() throws Exception {
connect();
call("초기화 연결 메시지");
}
@Override
public void destroy() throws Exception {
disConnect();
}
}
이런식으로 InitializingBean, DisposableBean인터페이스를 implement 하고, override 해주면, 주입이 다 끝나고 해당 프로그램이 돌아가게 된다.
빈 등록 초기화, 소멸 메서드 지정
설정 정보에
@Bean(initMethod = "init", destroyMethod = "close")를 입력하면 초기화, 소멸 메서드를 지정할 수 있다.
public class NetworkClient {
private String url;
public NetworkClient() {
System.out.println("생성자 호출, url = " + url);
}
public void setUrl(String url) {
this.url = url;
}
public void connect() {
System.out.println("connect: " + url);
}
public void call(String message) {
System.out.println("call: " + url + " message = " + message);
}
public void disConnect() {
System.out.println("close + " + url);
}
public void init() {
System.out.println("NetworkClient.init");
connect();
call("초기화 연결 메시지");
}
public void close() {
System.out.println("NetworkClient.close");
disConnect();
}
}
이런 식으로 init와 close에서 초기화, 종료를 해주도록 하고
@Configuration
public class LifeCycleConfig {
// NetworkClient 빈을 설정하는 메서드
@Bean(initMethod = "init", destroyMethod = "close")
public NetworkClient networkClient() {
// NetworkClient 객체 생성
NetworkClient networkClient = new NetworkClient();
// URL 설정
networkClient.setUrl("http://hello-spring.dev");
// 생성된 객체 반환
return networkClient;
}
}
이렇게 빈 등록할 때 초기화, 종료 메서드를 설정해주면 된다.
이때 종료메서드는 따로 적어주지 않아도 되는데, 그 이유는 @Bean의 destroyMethod는 기본값이 (inferred)(추론)으로 되어있기 때문이다.
어노테이션 @PostConstruct, @PreDestroy
결론적으로 이걸 사용하면 된다.
@PostConstruct
public void init() {
System.out.println("NetworkClient.init"); connect();
call("초기화 연결 메시지");
}
@PreDestroy
public void close() {
System.out.println("NetworkClient.close");
disConnect();
}
단순히 두 어노테이션을 메서듸 위에 붙여주면 된다.
최신 스프링에서 가장 권장하는 방식이고
`javax.annotation.PostConstruct라서 스프링이 아닌 다른 컨테이너에서도 잘 동작한다.
하지만 유일한 단점은 외부 라이브러리에는 적용하지 못한다는 것이다. 따라서 이럴 때는 그냥 @Bean 기능을 사용한다
출처
인프런 김영한 스프링 핵심원리 - 기본편
스프링 핵심 원리 - 기본편 강의 | 김영한 - 인프런
김영한 | , 스프링 핵심 원리를 이해하고, 성장하는 백엔드 개발자가 되어보세요! 📢 수강 전 확인해주세요! 본 강의는 자바 스프링 완전 정복 시리즈의 두 번째 강의입니다. 우아한형제들 최연
www.inflearn.com
'Back-end > Spring' 카테고리의 다른 글
[Spring] 웹 애플리케이션의 이해 (0) | 2025.03.30 |
---|---|
[Spring] 빈 스코프 (1) | 2025.03.11 |
[Spring] 의존관계 자동 주입 (1) | 2025.02.27 |
[Spring] 컴포넌트 스캔 (2) | 2024.11.29 |
[Spring] 싱글톤 컨테이너 (3) | 2024.11.14 |