[Spring] 기본_빈 생명 주기 콜백

gayoung·2022년 3월 26일
0

1. 빈 생명주기 콜백 시작

  • 데이터베이스 커넥션 풀처럼 애플리케이션 시작 시점에 필요한 연결을 미리 해두고, 애플리케이션 종료 시점에 연결을 모두 종료하는 작업을 진행하기 위해서는 객체의 초기화 작업, 종료 작업이 필요

2. 스프링 빈의 이벤트 라이프사이클

  1. 스프링 컨테이너 생성
  2. 스프링 빈 생성
  3. 의존 관계 주입
  4. 초기화 콜백: 빈이 생성되고 빈의 의존 관계 주입이 완료된 후 호출
  5. 로직
  6. 소멸 전 콜백: 빈이 소멸되기 직전에 호출
  7. 스프링 종료
  • 스프링빈의 라이프사이클
  • 객체생성 -> 의존관계 주입
  • 생성자 주입의 경우는 예외!! -> 객체만들 때 이미 스프링빈이 파라미터에 같이 들어가야함
  • 스프링 빈은 객체를 생성하고, 의존관계 주입이 다 끝난 다음에야 필요한 데이터를 사용할 수 있는 준비완료됨.
  • 따라서 초기화 작업은 의존관계 주입이 모두 완료되고 난 다음에 호출해야 한다.
  • 초기화란? 객체가 외부랑 진짜 연결해야할 때(처음 제대로 일 시작할 때)
  • 의존관계 주입이 완료되면, 스프링빈에게 콜백 메서드를 통해 초기화시점 알려줌

객체의 생성과 초기화를 분리하자.

  • 최대한 생성자에서 다 해버리면 되는거 아닌가?(networkClient()에서 다 하면 안되나?) 파라미터 넘기고, 다 생성자 주입 시키면 안되는것?
    -> 객체 생성과 초기화 분리필요!
    -> 객체생성시에는 값 세팅정도만! 초기화는 외부연결과같은 무거운 일들!

3. 빈 생명 주기 콜백 방법

3-1. 인터페이스(InitializingBean, DisposableBean)

[ NetworkClient ]

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

[ BeanLifeCycleTest ]

@Configuration
static class LifeCycleConfig {
    @Bean
    public NetworkClient networkClient() {
        NetworkClient networkClient = new NetworkClient();  // 아직 url정보 안들어옴
        networkClient.setUrl("http://naver.dev"); 
        return networkClient;
        }
    }
}
  • 이 인터페이스는 스프링 전용 인터페이스로, 해당 코드가 스프링에 의존함
  • 초기화, 소멸 메서드의 이름을 변경할 수 없음
  • 외부 라이브러리에 적용할 수 없음
  • 최근에는 거의 사용하지 않습니다.

3-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;
    }
}
  • 스프링 코드에 의존하지 않으면서 설정 정보에 메서드를 자유롭게 지정할 수 있음
  • 외부 라이브러리에도 적용할 수 있음

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

[ NetworkClient ]

public class NetworkClient {
	private String url;

    public NetworkClient() {
		System.out.println("생성자 호출, 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() {
        connect();
        call("초기화 연결 메세지");
    }

    @PreDestroy
    public void close() {
        disconnect();
    }
}

[ BeanLifeCycleTest ]

@PostConstruct
public void init(){
    System.out.println("NetworkClient.init");
    connect();
    call("초기화 연결 메시지");
    // 스프링의존관계 끝나고 호출해줌
}

@PreDestroy
public void close() {
    System.out.println("NetworkClient.close");
    disconnect();
}
  • 최신 스프링에서 가장 권장하는 방법
  • 스프링에 종속적이지 않은 자바 표준
  • 외부 라이브러리에는 적용하지 못함

0개의 댓글