gpt4 book ai didi

java - 追查 Spring 的 "not eligible for auto-proxying"的原因

转载 作者:IT老高 更新时间:2023-10-28 13:03:45 32 4
gpt4 key购买 nike

当您开始弄乱 Spring 的自动代理的东西时,您经常会遇到记录在案的这种行为:

Classes that implement the BeanPostProcessor interface are special, and so they are treated differently by the container. All BeanPostProcessors and their directly referenced beans will be instantiated on startup, as part of the special startup phase of the ApplicationContext, then all those BeanPostProcessors will be registered in a sorted fashion - and applied to all further beans. Since AOP auto-proxying is implemented as a BeanPostProcessor itself, no BeanPostProcessors or directly referenced beans are eligible for auto-proxying (and thus will not have aspects 'woven' into them.

For any such bean, you should see an info log message: “Bean 'foo' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)”.

换句话说,如果我编写自己的 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 .那个 bean 应该是罪魁祸首。

背景

想象一下这种情况:

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

当 Spring 必须创建 config (因为它是 FooPP 的依赖项),它有一个问题:契约(Contract)说所有 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 factory ...

在此示例中,可以打破其中一个循环依赖项。您可以制作FooPP实现BeanFactoryAware让 Spring 注入(inject) BeanFactory进入后处理器。这样,您就不需要 Autowiring 。

在后面的代码中,你可以懒洋洋地请求 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(...);
}

( source for LazyInit )

要打破 bean 工厂和后处理器之间的循环,您需要在 XML 配置文件中配置后处理器。 Spring 可以读取并构建所有结构而不会感到困惑。

关于java - 追查 Spring 的 "not eligible for auto-proxying"的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1201726/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com