[스프링] 스프링 빈 처리
용어
- 인스턴스화되어 객체가 되는 것: 클래스 = 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
인지 아니면 특정 값인지는 확인하지 않는다. @Required
는 setter
메서드에도 지정 가능하다. @Required
를 지정한 프로퍼티에 값이 없으면 BeanInitializationException
예외가 발생된다.
참고
- 스프링 5 레시피 (4판) : 스프링 애플리케이션 개발에 유용한 161가지 문제 해결 기법 (전2권) (마틴 데니엄, 다니엘 루비오, 조시 롱 공저/이일웅 역)
Comments