[Spring] 빈 생명주기 콜백

hi·2022년 11월 6일

스프링 빈은 간단하게 다음과 같은 라이프 사이클을 가진다
객체 생성 -> 의존관계 주입

스프링 빈은 객체를 생성하고 의존관계 주입이 끝나면, 필요한 데이터를 사용할 수 있는 준비가 완료된다.
따라서 초기화 작업은 의존관계 주입이 완료되고 난 후에 호출해야 한다.
이 초기화 시점을 콜백 메서드를 통해 알 수 있다

또한 스프링 컨테이너가 종료되기 직전 소멸 콜백을 준다

+) 객체의 생성과 초기화를 분리할 것
초기화는 무거운 동작을 수행하기에 두가지를 명확하게 나누는 것이 유지보수 관점에서 좋음


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

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

  • 초기화 콜백 : 빈이 생성되고, 빈의 의존관계 주입이 완료된 후 호출
    소멸전 콜백 : 빈이 소멸되기 직전에 호출


인터페이스 InitializingBean, DisposableBean

InitializingBean

  • afterPropertiesSet()
  • 초기화 지원

DisposableBean

  • destroy()
  • 소멸 지원
public class NetworkClient implements InitializingBean, DisposableBean {

    @Override
    public void afterPropertiesSet() throws Exception { //의존관계 주입이 끝나면 호출
		...
    }

    @Override
    public void destroy() throws Exception { //종료될 때 호출
		...
    }
}
@Configuration
static class LifeCycleConfig {

	@Bean
	public NetworkClient networkClient() {
		...
	}
}

단점

  • 스프링 전용 인터페이스에 의존
  • 메서드 이름 변경 불가
  • 코드 수정을 할 수 없는 외부 라이브러리에 적용 불가


빈 등록 초기화, 소멸 메서드 지정

@Bean(initMethod = "", destroyMethod = "")

  • 메서드 이름 변경 가능
  • 스프링 빈이 스프링 코드에 의존하지 않음
  • 코드가 아닌 설정 정보를 사용 -> 외부 라이브러리에 적용 가능

@Bean - destroyMethod 속성

  • 라이브러리는 대부분 close , shutdown 이라는 이름의 종료 메서드를 사용

  • destroyMethod 속성의 기본값은 (inferred) (추론)
    👉 close , shutdown 라는 이름의 메서드를 추론하여 자동으로 호출

  • 추론 기능을 사용하지 않으려면 destroyMethod="" 처럼 빈 공백 지정

public class NetworkClient {

	public void init() {
		...
    }
    
	public void close() {
		...
	}
}
@Configuration
static class LifeCycleConfig {

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


@PostConstruct, @PreDestroy

  • 스프링에서 가장 권장
  • 자바에서 지원 -> 스프링이 아닌 다른 컨테이너에서도 동작
  • 외부 라이브러리에 적용 불가 (@Bean의 initMethod , destroyMethod 사용하기)
public class NetworkClient {

	@PostConstruct
	public void init() {
		...
	}
    
	@PreDestroy
	public void close() {
 		...
    }
}
@Configuration
static class LifeCycleConfig {

	@Bean
	public NetworkClient networkClient() {
		...
	}
}

💡 @PostConstruct vs @EventListener

@PostConstruct

  • AOP 같은 부분이 다 처리되지 않은 시점에 호출될 수 있음
    ex. @Transactional 과 관련된 AOP가 적용되지 않은 상태로 호출

@EventListener(ApplicationReadyEvent.class)

  • AOP를 포함한 스프링 컨테이너가 완전히 초기화된 이후 호출

0개의 댓글