追查Spring“不符合自动代理资格”的原因
当你开始使用Spring的自动代理之类的东西时,通常会遇到以下记录的行为:
实现BeanPostProcessor接口的类是特殊的,因此容器对它们的处理方式有所不同。作为ApplicationContext特殊启动阶段的一部分,将在启动时实例化所有BeanPostProcessor及其直接引用的Bean,然后所有这些BeanPostProcessor将以排序的方式注册-并应用于所有其他Bean。由于AOP自动代理是作为BeanPostProcessor本身实现的,因此没有BeanPostProcessor或直接引用的bean都可以进行自动代理(因此不会包含“编织”的方面)。
对于任何此类bean,你应该看到一条信息日志消息:“ Bean’foo’不适合所有BeanPostProcessor处理(例如:不适合自动代理)”。
换句话说,如果我编写了自己的BeanPostProcessor,并且该类直接在上下文中引用了其他Bean,则这些被引用的Bean将不符合自动代理的资格,并且会记录一条消息。
我的问题是,很难找到直接引用的位置,因为“直接引用”实际上可能是一系列传递依赖关系,最终导致应用程序上下文中的bean数量减少了一半。Spring所能提供的只是一条信息消息,除了告诉你何时在此引用网络中捕获到bean之外,并没有什么帮助。
我正在开发的BeanPostProcessor确实具有对其他bean的直接引用,但是它的引用集非常有限。尽管如此,根据日志消息,我上下文中几乎所有的bean都被排除在自动代理之外,但是我看不到这种依赖发生在哪里。
有没有人找到更好的方法来追踪这种情况?
回答:
请遵循以下方法:
BeanPostProcessorChecker
在你的IDE中打开(这是的内部类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 时,情况会变得更糟:
@Configurationpublic class BadSpringConfig {
@Lazy @Bean public Config config() { return new Config(); }
@Lazy @Bean public FooPP fooPP() { return new FooPP(); }
}
每个配置类都是一个bean。这意味着要从中建立一个bean工厂BadSpringConfig
,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(...);
}
以上是 追查Spring“不符合自动代理资格”的原因 的全部内容, 来源链接: utcz.com/qa/427749.html