programing

Spring의 "자동 프록시 자격 없음" 원인 추적

magicmemo 2023. 9. 3. 12:31
반응형

Spring의 "자동 프록시 자격 없음" 원인 추적

Spring의 자동 프록시 장치를 만지작거리기 시작하면 문서화된 대로 다음과 같은 동작을 자주 보게 됩니다.

BeanPostProcessor 인터페이스를 구현하는 클래스는 특수하므로 컨테이너에서 다르게 처리됩니다.모든 BeanPostProcessor와 직접 참조되는 Bean은 ApplicationContext의 특수 시작 단계의 일부로 시작 시 인스턴스화되며, 모든 BeanPostProcessor는 정렬된 방식으로 등록되고 이후 모든 BeanPostProcessor에 적용됩니다.AOP 자동 프록시는 BeanPostProcessor 자체로 구현되므로 BeanPostProcessor 또는 직접 참조되는 BeanPostProcessor는 자동 프록시에 적합하지 않습니다(따라서 BeanPostProcessor에 'woven'한 측면이 없습니다).

이러한 Bean에 대해 "Bean 'foo'는 모든 BeanPostProcessor에서 처리할 수 없습니다(예: 자동 프록시 사용 불가)."라는 정보 로그 메시지가 표시됩니다.

즉, 제가 직접 BeanPostProcessor를 작성하고 해당 클래스가 컨텍스트에서 다른 Bean을 직접 참조하면 참조된 Bean은 자동 프록시를 사용할 수 없으며 메시지가 기록됩니다.

제 문제는 그 직접 참조가 어디에 있는지 추적하는 것이 매우 어려울 수 있다는 것입니다. 왜냐하면 "직접 참조"는 실제로 애플리케이션 맥락에서 콩의 절반을 차지하는 과도 의존성의 체인이 될 수 있기 때문입니다.봄이 여러분에게 주는 모든 것은 단 하나의 정보 메시지입니다. 그리고 그것은 여러분에게 콩이 이 참고 문헌 웹에 잡혔을 때를 알려주는 것 이상으로 큰 도움이 되지 않습니다.

제가 개발 중인 Bean Post Processor는 다른 콩과 직접적인 관련이 있지만, 매우 제한적인 관련 자료입니다.그럼에도 불구하고, 로그 메시지에 따르면, 제 컨텍스트에 있는 거의 모든 빈이 자동 프록시에서 제외됩니다. 하지만 저는 그 의존성이 어디서 발생하는지 알 수 없습니다.

더 좋은 방법을 찾은 사람이 있습니까?

다음 조리법을 따르십시오.

  1. 열다.BeanPostProcessorChecker당신의 IDE에서 (그것은 내부 클래스입니다.AbstractApplicationContext)

  2. 중단점 설정if (logger.isInfoEnabled()) {그 방법으로postProcessAfterInitialization

  3. 코드 실행

  4. 중단점에 도달하면 다음과 같은 전화를 찾습니다.getBean(String,Class<T>)당신의 스택 추적에서.

    이 통화들 중 하나는 다음을 만들기 위해 시도할 것입니다.BeanPostProcessor그 콩이 범인이 되어야 합니다.

배경

다음과 같은 상황을 상상해 보십시오.

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

이 Spring을 만들어야 할때 조창해야할때이할때▁when야▁spring조이▁spring.config이므로)FooPP), 다음과 같은 문제가 있습니다.계약서에는 모든 것이 나와 있습니다.BeanPostProcessor생성되는 모든 빈에 적용해야 합니다. 봄이 필요할 는.config 이상의 PP, 하이의즉 PP(상,FooPP 서비스 준비가 되지 않았습니다!

이것은 당신이 사용할 때 더 악화됩니다.@Configuration콩을 : " 빈을정는클래스하의이":

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

모든 구성 클래스는 빈입니다.그것은 콩 공장을 짓는 것을 의미합니다.BadSpringConfig은 포스트 .fooPP하지만 그러기 위해서는 먼저 콩 공장이 필요합니다.

이 예에서는 순환 종속성 중 하나를 해제할 수 있습니다.만들 수 있습니다.FooPPBeanFactoryAware를 맞으려면,BeanFactory포스트 프로세서로 이동합니다.그러면 자동 배선이 필요하지 않습니다.

코드의 후반부에서, 당신은 게으르게 콩을 요구할 수 있습니다.

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 구성 파일에서 포스트 프로세서를 구성해야 합니다.스프링은 그것을 읽고 혼란 없이 모든 구조물을 만들 수 있습니다.

, 되지 않은 는 이질을마기위해하않붕초, ▁the▁just▁by▁was붕에 의해 발생했습니다.BeanPostProcessor용사를 @Autowired, , ▁my▁defin▁to▁bean▁other▁effectition▁to▁every했다니ized▁be▁initial▁get습▁beforeow록▁and▁aut▁depend▁theencies,▁itsively 이전에 다른 모든 빈 정의를 초기화하도록 만들었습니다.BeanPostProcessor그 문제에 대해 발언권을 가질 기회를 얻었습니다.해결책은 BPP에 자동 배선을 사용하지 않는 것입니다.

도움이 될지 모르겠지만, Eclipse Spring IDE의 그래프 보기는 빈 참조를 분류하는 데 도움이 될 수 있을 것 같습니다.

언급URL : https://stackoverflow.com/questions/1201726/tracking-down-cause-of-springs-not-eligible-for-auto-proxying

반응형