Spring 강의/springMVC

springMVC 기본 - (8) 빈 생명주기 콜백

lxexjx 2022. 3. 12. 23:13

[빈 생명주기 콜백]

객체의 초기화와 종료 작업 필요.

NetworkClient 는 애플리케이션 시작 시점에 connect() 를 호출해서 연결을 맺어두어야 하고, 애플리케이션이 종료되면 disConnect() 를 호출해서 연결을 끊어야됨

 

<Networkclient>

public class NetworkClient {

    private String url;
    
    public NetworkClient() {
        System.out.println("생성자 호출, url = " + url);  //2.호출됨
        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);
    }
}

 

<BeanLifeCycleTest>

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();  //1. 생성자 호출
            networkClient.setUrl("http://hello-spring.dev");  //3. url넣어줌
            return networkClient;
        }
    }
}

 

1) 빈등록하면서 Networkclient에서 Networkclient생성자를 호출하고 

2) 그다음 생성자에서 connet() 호출

3) 그다음에 BeanLifeCycleTest에서 객체를 생성해서 url()을 넣어줌

 

생성자 부분을 보면 url 정보 없이 connect가 호출되는 것을 확인할 수 있다(아직 URL이 안들어옴).

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

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

 

스프링 빈은 객체를 생성하고, 의존관계 주입이 다 끝난 다음에야 필요한 데이터를 사용할 수 있는 준비가 완료.

따라서 초기화 작업은 객체 생성 작업이 아닌 객체 안에 필요한 값이 다 연결결돼있고 의존관계 주입이 모두 완료되고 난 다음에 호출해야 한다.

 

그런데 개발자가 의존관계 주입이 모두 완료된 시점을 어떻게 알 수 있을까?

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

 

스프링 빈의 이벤트 :

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

 

 


 

 

[스프링은 3가지 방법으로 빈 생명주기 콜백을 지원]

 

1.인터페이스(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();
    }
}

afterPropertiesSet() : property 세팅이 끝나면(의존 관계 주입이 끝나면) 호출됨

InitializingBean 은 afterPropertiesSet() 메서드로 초기화 

DisposableBean 은 destroy() 메서드로 소멸.

 

싱글톤 빈이라서 스프링 컨테이너가 올라올 때 생성되고 의존 관계 주입이 끝나면 afterPropertiesSet,destroy 호출

 

1) 생성자 호출되고

2)afterPropertiesSet() 호출되고

3)connet()해주고 call("초기화 연결 메세지") 띄우고

4)destroy()호출하고 스프링이 내려감

 

 

[빈 등록 초기화, 소멸 메서드] 

2.설정 정보에 초기화 메서드, 종료 메서드 지정

- 빈 등록 시점에 초기와 소멸 지정

<NetworkClient> 추가

public void init() {
    System.out.println("NetworkClient.init");
    connect();
    call("초기화 연결 메시지");
}
public void close() {
    System.out.println("NetworkClient.close");
    disConnect();
}
}

 

<BeanLifeCycleTest>

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

설정 정보에 초기화 소멸 메서드 지정

 

 

 

[@PostConstruct, @PreDestroy]

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

<NetworkClient>

@PostConstruct
public void init() {
    System.out.println("NetworkClient.init");
    connect();
    call("초기화 연결 메시지");
}
@PreDestroy
public void close() {
    System.out.println("NetworkClient.close");
    disConnect();
}

@Bean(initMethod = "init", destroyMethod = "close")이거 @Bean 으로 바꿔주고 로도 가능!