Spring/스프링 핵심 원리 - 기본편

[스프링 핵심 원리] 08. 빈 생명주기 콜백 - 인터페이스 InitializingBean, DisposableBean

HSY_mumu 2022. 5. 20. 17:06
728x90

(인프런) 김영한님의 스프링 핵심 원리-기본편을 공부하고 리뷰한 글입니다.

 

<스프링 빈 생명주기 콜백 지원 방법>

1) 인터페이스(InitializingBean, DisposableBean)

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

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


2. 인터페이스 InitializingBean, DisposableBean

1. NetworkClient 코드 수정

NetworkClient가 InitializingBean 과 DisposableBean 인터페이스를 implements 하도록 코드를 수정한다.

package hello.core.lifecycle;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

// 가상 네트워크 클라이언트
public class NetworkClient implements InitializingBean, DisposableBean {

    private String url; // 접속해야할 서버 url

    // 디폴트 생성자
    public NetworkClient() {
        System.out.println("생성자를 호출, url = " + 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 {
        System.out.println("NetworkClient.afterPropertiesSet");
        connect();
        call("초기화 연결 메시지");
    }

    // 소멸 메서드(빈이 종료될 때 호출)
    @Override
    public void destroy() throws Exception {
        System.out.println("NetworkClient.destroy");
        disConnect();
    }
}

1) InitializingBean: afterPropertiesSet() 메서드 초기화 지원

2) DisposableBean: destroy() 메서드 소멸 지원

 

2. 출력 결과

- 주입 완료 후, 초기화 메서드 호출

- 스프링 컨테이너의 종료가 호출된 후, 소멸 메서드 호출

 

3. 초기화, 소멸 인터페이스 단점

1) 해당 코드가 스프링 전용 인터페이스(InitializingBean, DisposableBena)에 의존

2) 초기화, 소멸 메서드의 이름 변경X.

- 초기화 메서드 명 = afterPropertiesSet, 소멸 메서드 명 = destroy

3) 내가 코드를 고칠 수 없는 외부 라이브러리에 적용X

 

(참고) 인터페이스를 사용하는 초기화, 종료 방법은 스프링 초창기에 나온 방법으로, 지금은 다음의 더 나은 방법들이 있어서 거의 사용하지 않는다.

 

Q. setUrl()은 의존관계 주입인가?

A. setUrl NetworkClient 의 String 값을 주입해주는 것으로 의존관계 주입이 아닌 값 주입에 해당한다.

의존관계 주입 = 객체를 주입

값 주입 = 값(String, int)를 주입

[출처] https://www.inflearn.com/questions/330983

 

Q. 아래와 같이 lifeCycleTest 코드에서 ac.close()를 빼면 NetworkClinet 클래스에서 Overriding한 destroy()가 호출되지 않는 이유는?

public class BeanLifeCycleTest {

    @Test
    public void lifeCycleTest() {
        ConfigurableApplicationContext ac = new AnnotationConfigApplicationContext(LifeCycleConfig.class);
        NetworkClient networkClient = ac.getBean(NetworkClient.class);
        //ac.close();     // 스프링 컨테이너 종료(ConfigurableApplicationContext 필요)
    }
    ...
}

A. 애플리케이션에서 new 로 직접 스프링 컨테이너를 생성한 경우, close()로 직접 종료를 해주지않으면 destroy()가 호출되지 않는다. 

예제에서처럼 new로 직접 스프링 컨테이너를 생성한다면, 직접  종료까지 해주는 것이 맞다. 컨테이너를 생성한 코드가 종료까지 책임을 져야하기 때문이다.

실무에서는 스프링 부트나 웹 서버에서 스프링을 사용하는데, 본인이 직접 스프링 컨테이너를 new로 생성하지 않는다. 그래서 서버 종료시 close()가 정상 호출되도록 장치가 마련되어 있다. 즉, 실무에서는 스프링 컨테이너를 직접 생성하지 않고 서버 종료시 자동으로 close()가 된다.

[출처] https://www.inflearn.com/questions/91767

728x90