当你开始搞乱Spring的自动代理服务器时,你经常会遇到这样的行为:
实现的类 BeanPostProcessor接口是 特别的,所以他们受到了待遇 不同的是容器。所有 BeanPostProcessors和它们直接相关 引用的bean将被实例化 在启动时,作为特殊的一部分 启动阶段 ApplicationContext,然后是所有这些 BeanPostProcessors将被注册 以有条不紊的方式 - 并应用于 所有其他豆类。自AOP以来 自动代理实现为 BeanPostProcessor本身没有 BeanPostProcessors或直接 引用的bean有资格获得 自动代理(因此不会有 方面'编织'进入他们。
对于任何这样的bean,你应该看到一个 info log message:“Bean'foo'不是 有资格获得所有人的处理 BeanPostProcessors(例如:不是 有资格进行自动代理)“。
换句话说,如果我编写自己的BeanPostProcessor,并且该类直接引用上下文中的其他bean,那么这些引用的bean将不符合自动代理的条件,并且会记录一条消息。
我的问题是跟踪直接引用的位置可能非常困难,因为“直接引用”实际上可能是一系列传递依赖关系,最终会占用应用程序上下文中的一半bean。 All Spring给你的是单个信息消息,除了告诉你什么时候bean被引用到这个引用网中时,它并没有多大帮助。
我正在开发的BeanPostProcessor确实有对其他bean的直接引用,但它是一组非常有限的引用。尽管如此,根据日志消息,我的上下文中的每个bean都被排除在自动代理之外,但我无法看到依赖性发生的位置。
有没有人找到更好的方法来追踪这个?
答案 0 :(得分:28)
按照这个食谱:
BeanPostProcessorChecker
(这是AbstractApplicationContext
的内部类)if (logger.isInfoEnabled()) {
postProcessAfterInitialization
上设置断点
当您点击断点时,在堆栈跟踪中查找getBean(String,Class<T>)
的调用。
其中一个调用将尝试创建BeanPostProcessor
。那豆应该是罪魁祸首。
<强>背景强>
想象一下这种情况:
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(...);
}
要中断bean工厂和后处理器之间的循环,需要在XML配置文件中配置后处理器。 Spring可以读取并构建所有结构而不会混淆。
答案 1 :(得分:20)
为了给这个问题带来一些结束,未初始化的对象图的崩溃是由BeanPostProcessor
使用@Autowired
来获取其依赖性引起的,并且autowire机制有效地导致了所有其他bean定义在BeanPostProcessor
有机会对此事发表意见之前进行初始化。解决方案不是为您的BPP使用自动装配。
答案 2 :(得分:4)
不确定它是否有任何帮助,但是Eclipse Spring IDE graph view看起来可能有助于整理bean引用..