Study/Spring Framework

[Spring] 빈(Bean) 생명주기 콜백

jonghne 2023. 10. 18. 20:09

빈 생명주기 콜백

스프링 빈이 생성될 때 초기화 콜백, 소멸될 때 소멸전 콜백을 호출해주는 기능이다.

 

주로 데이터베이스 커넥션 풀, 네트워크 소켓 처럼 애플리케이션 시작시점에 미리 연결해놓고 종료시점에 연결을 종료하는 작업에 사용된다. 

 

초기화 콜백은 의존관계 주입 이후, 소멸 콜백은 컨테이너 종료 직전 호출된다. 

 

✍🏻 스프링 빈의 이벤트 라이프 사이클 (싱글톤 기준)

출처 : https://catsbi.oopy.io/3a9e3492-f511-483d-bc65-183bb0c166b3

 

 

 

스프링이 지원하는 콜백 기능 구현 방법

1. InitializingBean , DisposableBean 인터페이스 사용

특정 빈에 InitializingBean, DisposableBean 인터페이스를 구현해서

초기화 작업은 afterPropertiesSet 메소드에, 소멸전 작업은 destroy 메소드에 구현한다.

public class NetworkClient implements InitializingBean, DisposableBean {
     ...

    @Override
    public void destroy() throws Exception {
        
    }

    @Override
    public void afterPropertiesSet() throws Exception {

    }
}

이 방법은 초기에 나온 방법으로 아래와 같은 단점이 있어서 거의 사용하지 않는다.

 

<단점>

1. 비즈니스 코드가 스프링 전용 인터페이스에 의존한다

2. 초기화, 소멸 메서드 이름을 변경할 수 없다.

3. 비즈니스 코드를 수정할 수 없는 외부 라이브러리에 적용할 수 없다.

 

 

 

2. 빈 등록 초기화, 소멸 메소드

설정 정보로 빈을 등록할 때 초기화, 소멸 메소드로 사용할 메서드 명을 지정하는 방법이다.

@Configuration
public class LifeCycleConfig{
    @Bean(initMethod = "init", destroyMethod="close")
    public NetworkClient networkClient() {
        return new NetworkClient();
    }
}
public class NetworkClient{
    // ...
    public void init() throws Exception {
        System.out.println("NetworkClient.init");
    }
    public void close() throws Exception {
        System.out.println("NetworkClient.close");
    }
}

 

메소드 이름을 자유롭게 지정할 수 있고, 스프링 빈이 스프링 코드에 의존하지 않는다.

또한 코드가 아닌 설정 정보를 사용하기 때문에, 외부 라이브러리에도 적용 가능하다.

 

✍🏻 종료 메소드 추론

destroyMethod 속성의 기본값은 inferred(추론)으로 등록되어 있다.

 

이 추론 기능은 destroyMethod 속성을 지정하지 않았을 때, Spring이 소멸 전 콜백 메서드일 것 같은 메서드를 추론해서 자동으로 호출해 주는 기능이다. (ex) 이름이 close 거나 shutdown와 같은 메서드)

 

만약 이 추론 기능을 사용하기 싫다면 destroyMethod 속성에 빈 공백을 지정하면 된다. (destoryMethod = "")

 

3. 애노테이션 @PostConstruct , @PreDestroy

최근 스프링에서는 3가지 방법 중 이 방법의 사용이 주로 권장된다.

 

초기화 메소드에 @PostConstruct, 소멸전 메소드에 @PreDestroy 자바 어노테이션을 붙여주면 된다.

@PostConstruct
public void init() throws Exception {
    System.out.println("NetworkClient.afterPropertiesSet");
    connect();

}

@PreDestroy
public void close() throws Exception {
    System.out.println("NetworkClient.destroy");
    disconnect();
}

이 어노테이션은 자바에서 제공하는 기술로 스프링에 의존적이지 않아서 스프링이 아닌 다른 컨테이너에서도 동작한다.

 

단, Bean으로 등록하려는 객체 내부에 직접 어노테이션을 적어야 하기 때문에 외부 라이브러리를 Bean으로 등록하는 경우에는 적용 할 수 없다 (이 경우에는 설정파일에 initMethod, destroyMethod 을 지정해줘야 한다)

 

출처 : 김영한님, 스프링 핵심 원리 기본편