본문 바로가기

Spring/Spring

[Spring] @PostConstruct, @PreDestroy

반응형

@PostConstruct와 @PreDestroy 애너테이션은 약간 이론적인 내용이 있기 때문에 두 애너테이션의 역할이 무엇인지 알아보기 전에 스프링 빈의 생명주기를 먼저 알아보겠습니다.

 

1. 스프링 빈의 생명주기

  1.  스프링 컨테이너 생성
  2. 스프링 빈 생성
  3. 의존관계 주입
  4. 사용
  5. 스프링 종료

 

스프링 빈은 생성과 의존 관계 주입이 동시에 이루어지는 것이 아니라 스프링 빈 객체를 생성을 한 뒤에 의존관계 주입을 실행합니다. 

이때 우리가 언제 의존관계 주입이 되는지, 또는 언제 스프링 빈이 소멸하는지를 알아보고 싶을 때 저 위의 두 애너테이션을 사용합니다.

 

두 애너테이션을 사용했을 때 생명주기를 나타내보자면

  1.  스프링 컨테이너 생성
  2. 스프링 빈 생성
  3. 의존관계 주입
  4. 초기화 콜백
  5. 사용
  6. 소멸 전 콜백
  7. 스프링 종료

이렇게 나타낼 수 있습니다.

초기화 콜백 : 빈이 생성되고, 빈의 의존관계 주입이 완료된 후 호

소멸 전 콜백 :  빈이 소멸되기 직전에 호출

 

영어 뜻으로도 알 수 있다시피 @PostConstruct는 생성된 이후, @PreDestroy는 소멸 직전을 나타낸다고도 볼 수 있습니다.

 

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;

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

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

 

import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

public class BeanLifeCycleTest {

    @Test
    public void lifeCycleTest() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(lifeCycleConfig.class);
        NetworkClient client = ac.getBean(NetworkClient.class);
        ac.close();
    }

    @Configuration
    static class lifeCycleConfig {
        @Bean
        public NetworkClient networkClient() {
            NetworkClient networkClient = new NetworkClient();
            networkClient.setUrl("http://hello.dev");
            return networkClient;
        }
    }
}

 

위의 두 코드를 통해 자세히 알아보겠습니다.

 

1. NetworkClient 메서드 실행

  1. "생성자 호출, url = null" 
  2. connect 메서드 실행 >> connect: null
  3. call 메서드 실행 >> call: null message = 초기화 연결 메시지

2. init 메서드 실행 (스프링 빈의 의존관계 주입이 완료되었다는 것을 알 수 있습니다.)

  1. Networkclient.init 출력
  2. connect 메서드 실행 >> connect: http://hello.dev 출력
  3. call 메서드 실행 >> call: http://hello.dev message = 초기화 연결 메시지 출력

3. close 메서드 실행 (스프링 빈이 소멸되기 직전이라는 것을 알 수 있습니다.)

  1. NetworkClient.close 출력
  2. disconnect 메서드 실행 >> close : http:hello.dev

 

 

실행 결과

 

아래 실행 결과는 @PostConstruct, @preDestroy를 주석처리 했을 때 실행 결과입니다.

위의 결과와 비교했을 때 init, close 메서드가 실행이 안 되는 것을 볼 수 있습니다.

즉, 빈의 의존관계 주입이 언제 시작되는지, 언제 소멸되는지를 확인할 수가 없는 것을 알 수 있습니다.

 

 

출처 : 인프런 - 스프링 핵심 원리 (기본편)

반응형