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

[빈 생명주기 콜백] 스프링 빈 생명주기 콜백 지원하는 방법 3가지 - 인터페이스, 설정 정보, 애노테이션

alsruds 2023. 12. 29. 02:41
🧐강의🧐
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard

 

애플리케이션 시작 시점에 필요한 연결을 생성하고, 종료 시점에 연결을 모두 종료하는 작업 진행 시,
객체의 초기화종료 작업이 필요하다
(ex. 데이터버이스 커넥션 풀, 네트워크 소켓)

 

  • 인터페이스 : IntializingBean, DisposableBean
  • 설정 정보 : 빈 등록 초기화, 소멸 메서드
  • (☆이 방법 사용하기!!) 애노테이션 : @PostConstruct, @PreDestroy

 

🚨문제 상황🚨

· 상황 가정

☑️ 가상의 외부 네트워크에 연결하는 하나의 객체 존재

☑️ NetworkClient : 애플리케이션 시작 시점 connect() 호출, 종료 시점 disconnect() 호출

☑️ 단순 문자 출력

 

1. 외부 연결 객체 생성하기

· test/java/hello.core/lifecycle/NetworkClient

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

 

2. 테스트 생성하기

· test/java/hello.core/lifecycle/BeanLifeCycleTest

public class BeanLifeCycleTest {

    @Test
    public void lifeCycleTest() {
        ConfigurableApplicationContext 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-spring.dev");
            return networkClient;
        }
    }
}

 

3. 테스트하기

객체 생성 후 수정자 주입으로 url 이 null 로 호출됨

 

 

💡해결 방법💡

1️⃣ 인터페이스 이용하기

· NetworkClient 에 InitializingBean, DisposableBean 구현하기

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

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

public class NetworkClient implements InitializingBean, DisposableBean {

    ...

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

초기화 & 소멸 메서드 호출

 

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

- 스프링 전용 인터페이스 의존

- 이름 변경 불가

- 외부 라이브러리 적용 불가

 

인터페이스 사용은 스프링 초창기의 방법으로, 지금은 거의 사용하지 않는다

 

2️⃣ 설정 정보에 메서드 등록하기

☑️ 메서드 이름 자유롭게 설정 가능

☑️ 스프링 코드 의존 X

☑️ 외부 라이브러리 적용 가능

 

· NetworkClient 에 연결 메서드 추가 : init() & close()

public class NetworkClient {

    ...

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

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

 

· BeanLifeCycleTest 에 빈 등록

public class BeanLifeCycleTest {

    ...

    @Configuration
    static class LifeCycleConfig {
        @Bean(initMethod = "init", destroyMethod = "close")
        public NetworkClient networkClient() {...}
    }
}

 

@Bean 의 destoryMethod : 종료 메서드 추론
- 대부분 라이브러리의 종료 메서드 이름 : close, shutdown (자동 호출, 따로 지정 안해도 됨)
- destroyMethod 기본값 : inferred
- 추론 기능 사용 안할 시, destroyMethod = " " 빈 공백으로 지정

 

3️⃣ 애노테이션 이용하기 (이 방법 사용!!)

☑️ 최신 스프링에서 가장 권장하는 방법

☑️ 외부 라이브러리 적용 불가 → @Bean 사용

 

· NetworkClient 에 애노테이션 추가하기

public class NetworkClient {

    ...

    @PostConstruct
    public void init() {...}

    @PreDestroy
    public void close() {...}
}

 

· BeanLifeCycleTest 로 테스트하기

public class BeanLifeCycleTest {

    ...

    @Configuration
    static class LifeCycleConfig {
        @Bean
        public NetworkClient networkClient() {...}
    }
}

가장 편리하게 초기화 & 종료 실행 가능