追查Spring的“不符合自动代理条件”的原因

当你开始搞乱Spring的自动代理的东西,你经常遇到这样的行为logging:

实现BeanPostProcessor接口的类是特殊的,所以它们被容器区别对待。 所有BeanPostProcessors及其直接引用的Bean将在启动时实例化,作为ApplicationContext的特殊启动阶段的一部分,然后所有BeanPostProcessors将以已sorting的方式注册 – 并应用于所有其他bean。 由于AOP自动代理被实现为一个BeanPostProcessor本身,所以没有BeanPostProcessors或直接引用的Bean有资格进行自动代理(因此不会有“编织”的方面)。

对于任何这样的bean,您应该看到一条信息日志消息:“Bean'foo'不适合所有BeanPostProcessors处理(例如:不适合自动代理)”。

换句话说,如果我编写自己的BeanPostProcessor,并且该类直接引用上下文中的其他Bean,那么这些引用的Bean将不具备自动代理的资格,并且会为此logging一条消息。

我的问题是跟踪直接引用的位置可能非常困难,因为“直接引用”实际上可能是一个传递依赖链,最终在应用程序上下文中占用一半的bean。 所有的spring给你的是单一的信息消息,并没有什么帮助,除了告诉你什么时候一个bean被引用到这个网页中。

我正在开发的BeanPostProcessor确实具有对其他bean的直接引用,但它是一组非常有限的引用。 尽pipe如此,根据日志消息,几乎我的上下文中的每个bean都被排除在自动代理之外,但是我无法看到依赖关系在哪里发生。

有没有人find一个更好的方法来跟踪这个呢?

遵循这个秘诀:

  1. 在您的IDE中打开BeanPostProcessorChecker (这是AbstractApplicationContext的内部类)
  2. 在方法postProcessAfterInitialization设置一个断点if (logger.isInfoEnabled()) {
  3. 运行你的代码
  4. 当你打断点时,在堆栈跟踪中查找对getBean(String,Class<T>)的调用。

    其中一个调用将尝试创build一个BeanPostProcessor 。 那个豆子应该是罪魁祸首。

背景

想象一下这种情况:

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

当Spring必须创buildconfig (因为它是FooPP的依赖)时,它有一个问题:合约说所有的BeanPostProcessor必须被应用到每个正在被创build的bean上。 但是当Spring需要config ,至less有一个PP(即FooPP )没有准备好服务!

当你使用@Configuration类来定义这个bean时,情况会变得更糟:

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

每个configuration类都是一个bean。 这意味着从BadSpringConfig构build一个bean工厂,Spring需要应用后处理器fooPP但为了这样做,它首先需要bean工厂…

在这个例子中,可能会破坏一个循环的依赖关系。 你可以让FooPP实现BeanFactoryAware来让Spring将BeanFactory注入到后处理器中。 这样,你不需要自动assembly。

在代码后面,你可以懒洋洋地问这个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 )

要打破豆工厂和后处理器之间的循环,需要在XMLconfiguration文件中configuration后处理器。 Spring可以读取并构build所有的结构而不会感到困惑。

为了解决这个问题,未初始化的对象图的崩溃是由使用@AutowiredBeanPostProcessor来获得它的依赖关系引起的,自动assembly机制有效地导致了每个其他的bean定义在我的BeanPostProcessor得到机会之前被初始化在这个问题上的一个说法。 解决scheme – 不要使用自动assembly为您的BPP …

不确定是否有任何帮助,但Eclipse Spring IDE的graphics视图看起来像可能有助于对bean引用进行sorting。