[spring] Spring BeanPostProcessor는 정확히 어떻게 작동합니까?

저는 Spring Core 인증을 위해 공부하고 있습니다. 저는 Spring이 어떻게 bean 라이프 사이클을 처리하는지 , 특히 bean 포스트 프로세서에 대해 약간의 의구심을 가지고 있습니다 .

그래서이 스키마가 있습니다.

여기에 이미지 설명 입력

그것이 의미하는 바는 나에게 매우 분명합니다.

다음 단계는 Bean 정의로드 단계에서 발생합니다.

  • @Configuration 클래스 처리 및 / 또는 @Components은 및 / 또는 검사하는 XML 파일을 구문 분석됩니다.

  • BeanFactory에 추가 된 Bean 정의 (각각 해당 ID 아래 색인화 됨)

  • 특수 BeanFactoryPostProcessor 빈이 호출되어 모든 빈의 정의를 수정할 수 있습니다 (예 : 속성-플레이스 홀더 값 대체).

그런 다음 Bean 생성 단계 에서 다음 단계가 수행됩니다 .

  • 각 빈은 기본적으로 열심히 인스턴스화됩니다 (종속성이 삽입 된 올바른 순서로 생성됨).

  • 종속성 주입 후 각 빈은 추가 구성 및 초기화가 발생할 수있는 사후 처리 단계를 거칩니다.

  • 사후 처리 후 빈은 완전히 초기화되고 사용할 준비가됩니다 (컨텍스트가 파괴 될 때까지 ID로 추적 됨).

좋아, 이것은 나에게 매우 명확하며 다음과 같은 두 가지 유형의 빈 포스트 프로세서있음을 알고 있습니다.

  • 이니셜 라이저 : 지시 된 경우 빈을 초기화합니다 (예 : @PostConstruct).

  • 그리고 모든 나머지 : 추가 구성이 가능하고 그 이전 또는 초기화 단계 이후에 실행할 수 있습니다

이 슬라이드를 게시합니다.

여기에 이미지 설명 입력

그래서 이니셜 라이저 빈 포스트 프로세서 ( @PostContruct 어노테이션으로 어노테이션 이있는 메소드 이며 setter 메소드 직후에 자동으로 호출 됨 (따라서 종속성 주입 후)) 가 무엇을 할 수 있는지는 매우 명확 합니다. 일부 초기화 일괄 처리를 수행합니다 (이전 예에서와 같이 캐시 채우기).

그러나 다른 빈 포스트 프로세서를 정확히 나타내는 것은 무엇입니까? 이러한 단계가 초기화 단계 이전 또는 이후에 수행된다는 것은 무엇을 의미 합니까?

따라서 내 빈이 인스턴스화되고 종속성이 주입되므로 초기화 단계가 완료됩니다 ( @PostContruct 주석 처리 된 메서드 실행 ). 초기화 단계 전에 Bean 포스트 프로세서가 사용된다는 것은 무엇을 의미합니까? @PostContruct 주석이 달린 메서드 실행 전에 발생한다는 의미 입니까? 의존성 주입 전에 (setter 메서드가 호출되기 전에) 발생할 수 있다는 의미입니까?

그리고 초기화 단계 후에 수행된다고 말할 때 정확히 무엇을 의미합니까 ? 그것은 @PostContruct 주석이 달린 메소드 의 실행 후에 발생한다는 것을 의미합니다 .

@PostContruct 주석이 달린 메서드 가 필요한 이유를 쉽게 이해할 수 있지만 다른 종류의 빈 포스트 프로세서에 대한 일반적인 예를 파악할 수 없습니다. 사용되는 경우에 대한 일반적인 예를 보여줄 수 있습니까?



답변

Spring doc은 BeanPostProcessor를 사용하여 콩 커스터마이징 에서 BPP를 설명합니다 . BPP 빈은 다른 빈보다 먼저 생성되고 새로 생성 된 빈과 상호 작용하는 특별한 종류의 빈입니다. 이 구조를 통해 Spring은 단순히 BeanPostProcessoryourself 를 구현하여 라이프 사이클 동작을 연결하고 사용자 정의 할 수있는 수단을 제공합니다 .

같은 사용자 지정 BPP

public class CustomBeanPostProcessor implements BeanPostProcessor {

    public CustomBeanPostProcessor() {
        System.out.println("0. Spring calls constructor");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println(bean.getClass() + "  " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println(bean.getClass() + "  " + beanName);
        return bean;
    }
}

호출되고 생성 된 모든 빈에 대한 클래스와 빈 이름을 인쇄합니다.

메소드가 빈의 라이프 사이클에 어떻게 부합하는지, 그리고 메소드가 정확히 언제 호출되는지 확인하려면 문서를 확인하십시오.

postProcessBeforeInitialization (Object bean, String beanName) Bean 초기화 콜백 (InitializingBean의 afterPropertiesSet 또는 사용자 정의 init-method와 같은) 전에이 BeanPostProcessor를 주어진 새 Bean 인스턴스에 적용하십시오.

postProcessAfterInitialization (Object bean, String beanName) Bean 초기화 콜백 (InitializingBean의 afterPropertiesSet 또는 사용자 정의 init-method와 같은) 후에 주어진 새 Bean 인스턴스에이 BeanPostProcessor를 적용하십시오.

중요한 점은

빈은 이미 속성 값으로 채워집니다.

@PostConstruct이 어노테이션이 postProcessAfterInitialization메소드 를 선언하는 편리한 방법 이라는 메모 와의 관계와 관련하여 Spring은 사용자가 등록 CommonAnnotationBeanPostProcessor하거나 <context:annotation-config />Bean 구성 파일을 지정하여 이를 인식 합니다. @PostConstruct메서드의 실행 여부는 속성에 postProcessAfterInitialization따라 다릅니다.order

여러 BeanPostProcessor 인스턴스를 구성 할 수 있으며 order 속성을 설정하여 이러한 BeanPostProcessor가 실행되는 순서를 제어 할 수 있습니다.


답변

빈 포스트 프로세서의 전형적인 예는 @Transactional어노테이션을 사용할 때와 같이 프록시 인스턴스에서 원래 빈을 래핑하려는 경우 입니다.

빈 포스트 프로세서는 빈의 원래 인스턴스를 전달 받게되며, 대상에있는 모든 메소드를 호출 할 수 있지만 애플리케이션 컨텍스트에 바인딩되어야하는 실제 빈 인스턴스를 반환합니다. 즉, 실제로 어떤 것을 반환 할 수 있습니다. 원하는 개체. 이것이 유용한 일반적인 시나리오는 빈 포스트 프로세서가 대상을 프록시 인스턴스로 래핑하는 경우입니다. 응용 프로그램 컨텍스트에 바인딩 된 빈에 대한 모든 호출은 프록시를 통과하고 프록시는 대상 빈에 대한 호출 전후에 몇 가지 마법을 수행합니다 (예 : AOP 또는 트랜잭션 관리).


답변

차이점은 BeanPostProcessor다음 상황에 맞는 초기화에 후크 호출 postProcessBeforeInitializationpostProcessAfterInitialization정의 된 모든 콩을 위해.

그러나 @PostConstruct생성자 또는 set 메소드 이후에 bean 생성을 사용자 정의하려는 특정 클래스에만 사용됩니다.


답변