ABAP DUMP ERROR 24시

빈 생명주기 콜백 정리 본문

[WEB]Back-end/Spring

빈 생명주기 콜백 정리

이운형 2022. 1. 30. 20:01
반응형

# 인프런 김영한의 스프링 핵심 원리 - 기본편을 개인적으로 정리한 글입니다.

 

정리


Q. 빈 라이프 사이클이 왜 필요해?

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

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

 

=> 시작 시점에는 미리 연결해두고 종료시점에는 모두 종료시키는 역할이 필요하다!

Q. 스프링 빈의 이벤트 라이프사이클 순서가 뭐야?

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

우리는 초기화 콜백과 소멸전 콜백을 신경써야한다.

 

Q.스프링의 빈 생명주기 콜백 크게 3가지 방법이 뭐야?

1.인터페이스(InitializingBean, DisposableBean) // implements를 사용후, @override 해서 사용한다.

2.설정 정보에 초기화 메서드, 종료 메서드 지정 //@Bean내부에 "init"과 destroyMethod를 지원해서 사용한다.

3.@PostConstruct, @PreDestroy 애노테이션 지원 //@PostConstruct, @PreDestroy를 사용한다. ///이거 써라!

 

Q.결론

@PostConstruct, @PreDestroy 애노테이션을 사용하자.

코드를 고칠 수 없는 외부 라이브러리를 초기화, 종료해야 하면 @Bean 의 initMethod , destroyMethod 를 사용하자.

 

살펴보기


Q. 빈 라이프 사이클이 왜 필요해? // Code로 확인하기

 

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

 

시작시 connect를 사용해서 호출하고 종료시 disconnect를 사용해서 종료하는 알고리즘을 만들었다고 가정하자!

그 후 기능들을 적용 시킬 TEST Code를 말들어 살펴보면,

public class BeanLifeCycleTest {
    @Test
    public void lifeCycleTest() {
        ConfigurableApplicationContext ac = new
                AnnotationConfigApplicationContext(LifeCycleConfig.class);
        NetworkClient client = ac.getBean(NetworkClient.class);
        ac.close(); //스프링 컨테이너를 종료, ConfigurableApplicationContext 필요
    }
    @Configuration
    static class LifeCycleConfig {
        @Bean
        public NetworkClient networkClient() {
            NetworkClient networkClient = new NetworkClient();
            networkClient.setUrl("http://hello-spring.dev");
            return networkClient;
        }
    }
}

LifeCycleTest() 안에 ConfigurableApplicationContext 를 통해 LifeCycleConfig.class를  의존관계를 가져오고,

AnnotationConfigApplicationContext를 통해 @configuration 내의 @Bean을 읽어온다.

 

하지만 결과는?

 

생성자 호출,

url = null

connect: null

call: null message = 초기화 연결 메시지

 

객체를 생성하는 단계에는 url이 없없기 때문에 null 이 발생하였고,

객체를 생성한 다음에 외부에서 수정자 주입을 통해서 setUrl() 이 호출되어야 url이 존재하게 된다.

 

Q.스프링의 빈 생명주기 콜백 크게 3가지 방법이 뭐야? // Code

1.인터페이스(InitializingBean, DisposableBean) // implements를 사용후, @override 해서 사용한다.

public class NetworkClient implements  DisposableBean, InitializingBean{

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

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("NetworkClient.afterPropertiesSet");
        connect();
        call("초기화 연결 메세지");

    }

    @Override
    public void destroy() throws Exception {
        System.out.println("NetworkCline.destory");
        disconnect();

    }
}

 

2.설정 정보에 초기화 메서드, 종료 메서드 지정 //@Bean내부에 "init"과 destroyMethod를 지원해서 사용한다.

 

 

public class Bean_init_close_lifecycle {

    private String url;


    public Bean_init_close_lifecycle(){
        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);

    }

    public void init()   {
        System.out.println("Bean_init_close_lifecycle.init");
        connect();
        call("초기화 연결 메세지");

    }


    public void close()   {
        System.out.println("Bean_init_close_lifecycle.close");
        disconnect();

    }


}

 

다음과 같이 init 메소드와 close()메소드를 만들어 준다음!

public class Bean_init_close_lifecycle_test {

    @Test
    public void lifeCycleTest(){
        ConfigurableApplicationContext ac = new AnnotationConfigApplicationContext(BeanLifeCycleTest.LifeCycleConfig.class);
        NetworkClient client = ac.getBean(NetworkClient.class);
        ac.close();


    }

    @Configuration
    static class LifeCycleConfig{

        @Bean(initMethod = "init", destroyMethod = "close")
        public Bean_init_close_lifecycle beanInitCloseLifecycle(){
            Bean_init_close_lifecycle bean_init_close_lifecycle = new Bean_init_close_lifecycle();
            bean_init_close_lifecycle.setUrl("https://hello-spring.dev");
            return bean_init_close_lifecycle;
        }

    }
}

@Bean에 initMethod에는 init메소드를,

destoryMethod에는 close메소드를 넣는다.

 

3.@PostConstruct, @PreDestroy 애노테이션 지원 //@PostConstruct, @PreDestroy를 사용한다.

public class Bean_postConstructor_predistroy {

    private String url;


    public Bean_postConstructor_predistroy(){
        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("Bean_postConstructor_predistroy.init");
        connect();
        call("초기화 연결 메세지");

    }

    @PreDestroy
    public void close()   {
        System.out.println("Bean_postConstructor_predistroy.close");
        disconnect();

    }


}

 

 

반응형
Comments