복붙노트

[SPRING] Spring의 "자동 프록시를 사용할 수 없음"원인 추적

SPRING

Spring의 "자동 프록시를 사용할 수 없음"원인 추적

Spring의 자동 프록시 기능을 사용하기 시작하면 다음과 같이 문서화 된대로이 동작을 자주 접하게됩니다.

즉, 내 자신의 BeanPostProcessor를 작성하고 해당 클래스가 컨텍스트에서 다른 Bean을 직접 참조하면 해당 참조 된 Bean은 자동 프록시에 적합하지 않으며 해당 효과에 메시지가 기록됩니다.

내 문제는 "직접 참조"가 실제로 애플리케이션 컨텍스트에서 빈의 절반을 차지하는 전이 종속성 체인 일 수 있기 때문에 직접 참조가 어디에 있는지 추적하는 것이 매우 어려울 수 있다는 것입니다. 모든 Spring은 단일 정보 메시지를 제공합니다. 콩이이 참조 웹에 걸렸을 때 알려주지 않고서는별로 도움이되지 않습니다.

내가 개발중인 BeanPostProcessor는 다른 bean에 대한 직접적인 참조를 가지고 있지만 매우 제한된 참조 세트입니다. 그럼에도 불구하고 내 컨텍스트의 거의 모든 bean은 로그 메시지에 따라 자동 프록시가 적용되지 않도록 제외되지만 그 종속성이 어디에서 발생하는지 볼 수 없습니다.

누구든지 이것을 추적하는 더 좋은 방법을 찾았습니까?

해결법

  1. ==============================

    1.이 제조법을 따르십시오 :

    이 제조법을 따르십시오 :

    배경

    이 상황을 상상해보십시오.

    public class FooPP implements BeanPostProcessor {
        @Autowire
        private Config config;
    }
    

    Spring이 config를 생성해야 할 때 (FooPP의 의존성이기 때문에), 문제가있다 : 계약서에 모든 BeanPostProcessor가 생성되는 모든 bean에 적용되어야한다고한다. 그러나 Spring이 config를 필요로 할 때, 서비스 준비가되어 있지 않은 적어도 하나의 PP (즉, FooPP)가있다!

    @Configuration 클래스를 사용하여이 Bean을 정의 할 때 이것은 더 나빠집니다.

    @Configuration
    public class BadSpringConfig {
         @Lazy @Bean public Config config() { return new Config(); }
         @Lazy @Bean public FooPP fooPP() { return new FooPP(); }
    }
    

    모든 구성 클래스는 bean입니다. 그것은 BadSpringConfig에서 빈 팩토리를 만드는 것을 의미합니다. Spring은 포스트 프로세서 fooPP를 적용해야하지만 그렇게하기 위해서는 먼저 bean factory가 필요합니다 ...

    이 예에서 순환 종속성 중 하나를 제거 할 수 있습니다. FooPP가 BeanFactoryAware를 구현하여 Spring이 포스트 프로세서에 BeanFactory를 삽입하도록 만들 수 있습니다. 그렇게하면 자동 와이어 링이 필요하지 않습니다.

    코드의 뒷부분에서 lazily가 bean을 요청할 수 있습니다.

    private LazyInit<Config> helper = new LazyInit<Config>() {
    
        @Override
        protected InjectionHelper computeValue() {
            return beanFactory.getBean( Config.class );
        }
    };
    
    @Override
    public Object postProcessBeforeInitialization( Object bean, String beanName ) throws BeansException {
         String value = helper.get().getConfig(...);
    }
    

    (LazyInit 소스)

    빈 팩토리와 포스트 프로세서 사이의주기를 깨기 위해서는 포스트 프로세서를 XML 설정 파일로 설정해야한다. Spring은 그것을 읽을 수 있고 혼동하지 않고 모든 구조를 만들 수 있습니다.

  2. ==============================

    2.이 질문에 일부 종결을하기 위해, 초기화되지 않은 객체 그래프의 붕괴는 BeanPostProcessor가 @Autowired를 사용하여 종속성을 얻음으로써 야기되었고, Autowire 메커니즘은 BeanPostProcessor가 가질 수있는 기회를 갖기 전에 다른 모든 Bean 정의를 효과적으로 초기화 시켰습니다. 그 문제에 대해서. 솔루션은 BPP에 자동 와이어 링을 사용하지 않는 것입니다.

    이 질문에 일부 종결을하기 위해, 초기화되지 않은 객체 그래프의 붕괴는 BeanPostProcessor가 @Autowired를 사용하여 종속성을 얻음으로써 야기되었고, Autowire 메커니즘은 BeanPostProcessor가 가질 수있는 기회를 갖기 전에 다른 모든 Bean 정의를 효과적으로 초기화 시켰습니다. 그 문제에 대해서. 솔루션은 BPP에 자동 와이어 링을 사용하지 않는 것입니다.

  3. ==============================

    3.어떤 도움이 필요한지 확실하지 않지만 Eclipse Spring IDE 그래프 뷰는 빈 참조를 정렬하는 데 도움이 될 것 같습니다.

    어떤 도움이 필요한지 확실하지 않지만 Eclipse Spring IDE 그래프 뷰는 빈 참조를 정렬하는 데 도움이 될 것 같습니다.

  4. from https://stackoverflow.com/questions/1201726/tracking-down-cause-of-springs-not-eligible-for-auto-proxying by cc-by-sa and MIT license