[스프링] 스프링 빈 처리

용어

  • 인스턴스화되어 객체가 되는 것: 클래스 = POJO 클래스
  • 클래스를 인스턴스화한 것: 빈 인스턴스 = POJO 인스턴스 = 객체 인스턴스


빈 초기화/제거

빈 인스턴스는 생성 이후 초기화(initialize)되고 더 이상 사용되지 않아 컨테이너에서 소멸(또는 폐기)(destory)되는 과정을 거친다. 즉, 빈(POJO)은 적절한 시점에 인스턴스화되어 생성된 후 사용되다가 소멸되기까지 일련의 생명 주기를 가지고 있다고 볼 수 있다.

구성 클래스에서 @Bean을 사용하여 빈 객체를 생성할 때 initMethod, destroyMethod 속성을 설정하면 스프링은 해당 메서드를 각각 초기화 콜백, 소멸 콜백 메서드로 인지한다. 구성 클래스 내에서 @Bean의 속성을 사용하는 대신 구성 클래스 외부에서 @Component를 사용하여 빈을 정의하는 경우 메서드에 @PostConstruct@PreDestroy를 설정하여 객체 초기화 및 소멸 콜백 메서드를 정의할 수도 있다.

스프링은 기본적으로 모든 빈 인스턴스를 즉시 초기화(eager initialization)한다. 즉시 초기화란 애플리케이션 시동과 동시에 빈 인스턴스를 초기화하는 것을 말한다. 그러나 요청하기 전까지 빈 초기화 과정을 지연시키는 것이 필요할 수 있으며 빈 인스턴스를 나중에 초기화하는 것을 지연 초기화(lazy initialization)라고 한다. 빈 인스턴스를 지연 초기화하면 애플리케이션 시동 시점에 리소스를 소모하지 않아도 되므로 전체 시스템 리소스를 절약할 수 있다. 네트워크 접속, 파일 처리 등 무거운 작업을 처리하는 빈의 경우 지연 초기화기 더 적합하다. 빈에 지연 초기화를 적용하기 위해서는 클래스에 @Component와 함께 @Lazy 어노테이션을 설정하면 된다. @Lazy를 지정한 빈 인스턴스는 애플리케이션이 요청하거나 다른 빈이 해당 빈을 참조하기 전까지 초기화되지 않는다.

늦은 초기화를 사용하는 경우 해당 빈이 초기화되지 않았는데 참조하여 사용하는 상황이 생길 수 있으며 이는 의도치 않은 애플리케이션 동작이 될 수 있다. @DependsOn 어노테이션은 어떤 빈이 다른 빈 보다 먼저 초기화되도록 강제함으로써 빈을 초기화하는 순서를 보장하여 빈을 사용하기 전에 해당 빈이 먼저 초기화되도록 한다.


빈 후처리 및 검증

빈 초기화 콜백 메서드의 실행 전후에 어떤 코드를 실행하기 위해서는 빈 후처리기(bean post-processor)를 사용하면 된다. 기본적으로 빈 후처리기는 스프링 컨테이너 내부의 모든 빈 인스턴스를 대상으로 한다. 빈 후처리기를 사용하여 빈 프로퍼티가 올바른지 확인하거나 어떤 기준에 따라 빈 프로퍼티를 변경할 수 있다. 또한 전체 빈 인스턴스를 상대로 어떤 작업을 수행할 수도 있다.

빈 후처리기에 해당하는 인터페이스는 BeanPostProcessor이다. 이 인터페이스를 구현한 빈을 애플리케이션 컨텍스트에 컴포넌트로 등록하면 스프링은 모든 빈 인스턴스에 postProcessBeforeInitialization(), postProcessAfterInitialization() 두 메서드를 적용하여 실행한다. 애플리케이션 컨텍스트는 BeanPostProcessor 구현 빈을 감지하고 컨테이너 내에 있는 다른 빈 인스턴스에 해당 후처리 메서드를 일괄 적용한다.

postProcessBeforeInitialization() 메서드는 빈 초기화 이전에 실행되며 postProcessAfterInitialization() 메서드는 빈 초기화 이후에 실행된다. 이 두 메서드를 사용함으로써 빈 초기화 전후에 빈 상태를 조사, 수정, 확인하는 등의 로직이 실행되도록 할 수 있다. 두 메서드는 빈 인스턴스와 빈 이름을 인자로 전달받으며 내부 로직이 없더라도 반드시 원본 빈 인스턴스를 반환해야 한다.

애플리케이션 컨텍스트의 모든 빈 인스턴스를 대상으로 빈 후처리 로직을 적용하는 대신 특정 빈 인스턴스에 대해서만 적용하기 위해서는 메서드 내에서 인스턴스의 타입을 체크하는 instanceof를 사용하면 된다.

빈의 특정 프로퍼티에 값이 설정되었는지 확인하기 위해서는 @Required 어노테이션을 사용한다. @Required는 스프링에 내장된 후처리기인 RequiredAnnotationBeanPostProcessor가 지원하는 어노테이션이다. RequiredAnnotationBeanPostProcessor 후처리기는 @Required를 지정한 빈 프로퍼티에 값이 설정되었는지 확인한다. 프로퍼티의 값 설정 여부만 확인할 뿐 값이 null인지 아니면 특정 값인지는 확인하지 않는다. @Requiredsetter 메서드에도 지정 가능하다. @Required를 지정한 프로퍼티에 값이 없으면 BeanInitializationException 예외가 발생된다.


참고

  • 스프링 5 레시피 (4판) : 스프링 애플리케이션 개발에 유용한 161가지 문제 해결 기법 (전2권) (마틴 데니엄, 다니엘 루비오, 조시 롱 공저/이일웅 역)

Comments