当你开始搞乱Spring的自动代理服务器时,你经常会遇到这样的行为:

  

实现的类   BeanPostProcessor接口是   特别的,所以他们受到了待遇   不同的是容器。所有   BeanPostProcessors和它们直接相关   引用的bean将被实例化   在启动时,作为特殊的一部分   启动阶段   ApplicationContext,然后是所有这些   BeanPostProcessors将被注册   以有条不紊的方式 - 并应用于   所有其他豆类。自AOP以来   自动代理实现为   BeanPostProcessor本身没有   BeanPostProcessors或直接   引用的bean有资格获得   自动代理(因此不会有   方面'编织'进入他们。

     

对于任何这样的bean,你应该看到一个   信息日志消息:“ Bean'foo'不是   有资格获得所有人的处理   BeanPostProcessors(例如:不是   有资格进行自动代理)”。

换句话说,如果我编写自己的BeanPostProcessor,并且该类直接引用上下文中的其他bean,那么这些引用的bean将不符合自动代理的条件,并且会记录一条消息。

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

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

有没有人找到更好的方法来追踪这个?

有帮助吗?

解决方案 2

为了给这个问题带来一些结束,未初始化的对象图的崩溃是由 BeanPostProcessor 引起的,它使用 @Autowired 来获取它的依赖关系,以及autowire机制在我的 BeanPostProcessor 有机会对此事发表意见之前,有效地导致所有其他bean定义被初始化。解决方案不是为您的BPP使用自动装配。

其他提示

按照这个食谱:

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

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

  6. <强>背景

    想象一下这种情况:

    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 构建一个bean工厂,Spring需要应用后处理器 fooPP ,但为了做到这一点,它首先需要bean工厂...

    在此示例中,可以破坏其中一个循环依赖项。您可以使 FooPP 实现 BeanFactoryAware 以使Spring将 BeanFactory 注入后处理器。这样,您就不需要自动装配了。

    稍后在代码中,您可以懒惰地请求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的来源

    要中断bean工厂和后处理器之间的循环,需要在XML配置文件中配置后处理器。 Spring可以读取并构建所有结构而不会混淆。

不确定是否有任何帮助,但Eclipse Spring IDE 图表视图看起来可能有助于整理bean引用..

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top