追查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都被排除在自动代理之外,但是我看不到这种依赖发生在哪里。

有没有人找到更好的方法来追踪这种情况?

回答:

请遵循以下方法:

  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时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。这意味着要从中建立一个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

回到顶部