본문 바로가기
Spring

[Spring] 빈 생명주기 콜백

by 당코 2022. 12. 28.

데이터베이스 커넥션 풀이나, 네트워크 소켓처럼 애플리케이션 시작 시점에 필요한 연결을 미리 해두고,

애플리케이션 종료 시점에 연결을 모두 종료하는 작업을 진행하려면, 객체의 초기화와 종료 작업이 필요하다.


스프링 빈의 라이프사이클

스프링 빈은 간단하게 다음과 같은 라이프 사이클을 가진다.

객체생성 -> 의존관계 주입

따라서 초기화 작업은 의존관계 주입이 끝난 후에 수행되어야 한다.

그럼 어떻게 의존관계 주입이 끝난 시점을 알 수 있을까?

스프링은 의존관계 주입이 완료되면 스프링 빈에게 콜백 메서드를 통해서 초기화 시점을 알려주는 다양한 기능을 제공한다. 또한 스프링은 스프링 컨테이너가 종료되기 직전에 소멸 콜백을 준다

스프링 빈의 이벤트 라이프사이클

스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존관계 주입 -> 초기화 콜백 -> 사용 -> 소멸 전 콜백 -> 스프링 종료

 

간단한 외부 네트워크 객체를 통해 초기화 작업과 종료 작업을 수행하는 방법에 대해 살펴보겠다.

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();
 	}
}

서비스 시작시 connect()를 호출하고, 서비스 종료 시 disConnect()를 호출하고자 한다.

init 메서드와 close 메서드를 초기화, 소멸 메서드로 지정하였다.

 

빈 등록 초기화, 소멸 메서드 지정

설정 정보에 @Bean(initMethod = "init", destroyMethod = "close")처럼 초기화, 소멸 메서드를 지정할 수 있다

@Configuration
static class LifeCycleConfig {

	@Bean(initMethod = "init", destroyMethod = "close")
   	public NetworkClient networkClient() {
 		NetworkClient networkClient = new NetworkClient();
 		networkClient.setUrl("http://hello-spring.dev");
 		return networkClient;
 	}
}

@Bean의 initMethod와 destroyMethod에 원하는 초기화, 소멸 메서드의 이름을 지정해 주면 적용할 수 있다.

설정 정보를 이용하기 때문에 코드를 고칠 수 없는 외부 라이브러리에도 적용이 가능하다는 장점이 있다.

destroyMethod의 경우 추론 기능이 있어 자동으로 close, shutdown이라는 이름의 메서드를 자동으로 호출한다.

즉, 직접 스프링 빈으로 등록하면 종료 메서드는 따로 적어주지 않아도 동작한다.

따라서 이 추론 기능을 사용하지 않기 위해서는 destroyMethod = "" 로 지정해 주면 된다.

 

애노테이션 @PostConstruct, @PreDestroy

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);
 	}
 
 	@PostConstruct
 	public void init() {
 		System.out.println("NetworkClient.init");
 		connect();
 		call("초기화 연결 메시지");
 	}
    
  	@PreDestroy
 	public void close() {
 		System.out.println("NetworkClient.close");
 		disConnect();
 	}
}

초기화 메서드에 @PostConstruct, 소멸 메서드에 @PreDestroy를 붙여주면 된다.

두 어노테이션은 스프링에 종속되지 않는 자바 표준이기 때문에 스프링이 아닌 다른 컨테이너에서도 잘 작동한다.

코드를 고쳐야 하기 때문에 외부 라이브러리에는 적용하지 못한다는 단점이 있다.

 

결론

  • @PostConstruct, @PreDestroy를 사용하는 것을 권장한다.
  • 코드를 고칠 수 없는 외부 라이브러리를 초기화 종료해야 한다면 설정정보의 @Bean에 @initMethod, @destroyMethod를 사용하자.

 

출처 : https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard

'Spring' 카테고리의 다른 글

[Spring] 스프링 MVC의 구조  (0) 2023.01.09
[Spring] MVC 패턴  (0) 2023.01.04
[Spring] 같은 타입으로 조회된 빈이 여러 개일 경우  (0) 2022.12.28
[Spring] 의존관계 자동 주입  (0) 2022.12.27
[Spring] 컴포넌트 스캔  (0) 2022.12.27