gpt4 book ai didi

java - 为什么@Configuration 类中的@Autowired 字段为空?

转载 作者:搜寻专家 更新时间:2023-11-01 02:03:03 24 4
gpt4 key购买 nike

这是来自 the Spring documentation 的示例, 第 6.12.5 节:

@Configuration
public class ServiceConfig {

@Autowired
private AccountRepository accountRepository;

@Bean
public TransferService transferService() {
return new TransferServiceImpl(accountRepository);
}

}

我的问题是:为什么一定要在 new TransferServiceImpl() 使用之前创建 accountRepository?顺便说一下,我不明白 Spring 如何知道第二个依赖于第一个正在设置的(除非它通过 transferService() 字节码)。是不是因为 Spring 做事的顺序保证了 @Autowired 变量在可能调用 @Bean 方法之前被处理?处理顺序是什么?什么样的情况会导致Spring乱序处理?

我问的原因是我遇到这样的情况不起作用,即 new 正在使用 null 参数执行。 @Autowired 变量设置得太晚,或者根本没有设置(我猜是后者,基于一些 log4j.logger.org.springframework.beans 调试输出,但我不确定)。情况当然要复杂得多——它是一个大型应用程序,并且在配置类中有更多的 @Autowired@Bean 定义。使用 @DependsOn 没有帮助。在我得到一个最小的例子之前,通过删除代码来缩小问题范围会花费很多时间,但我想看看我是否可以通过了解更多关于 Spring 如何处理事物的细节来深入了解这个问题,然后再开始困难的代码减少路径。

最佳答案

why must it happen that accountRepository is created before it's used by new TransferServiceImpl()?

事实并非如此。 accountRepository 可能被视为 null

来自 documentation you linked 中的注释(它的最新版本)

Make sure that the dependencies you inject that way are of the simplest kind only. @Configuration classes are processed quite early during the initialization of the context and forcing a dependency to be injected this way may lead to unexpected early initialization. Whenever possible, resort to parameter-based injection as in the example above.

Also, be particularly careful with BeanPostProcessor and BeanFactoryPostProcessor definitions via @Bean. Those should usually be declared as static @Bean methods, not triggering the instantiation of their containing configuration class. Otherwise, @Autowired and @Value won’t work on the configuration class itself since it is being created as a bean instance too early.

总而言之,Configuration 类最终将只是应用程序上下文中的另一个 bean。因此,它将由所有注册的 BeanPostProcessor 处理。 bean 。

@AutowiredAutowiredAnnotationBeanPostProcessor 处理.据推测,您正在使用自动注册的 AnnotationConfigApplicationContext

在你的例子中,这是不完整的,因为

...but determining exactly where the autowired bean definitions are declared is still somewhat ambiguous

但是,我们可以假设一些其他配置为 AccountRepository bean 提供了 bean 定义。一旦应用程序上下文实例化了 ServiceConfig bean,它就可以对其进行后处理并注入(inject) @Autowired 目标。

@Autowired 目标在 @Configuration bean 实例中可能为 null 的唯一原因是您试图在 之前读取它code>AutowiredAnnotationBeanPostProcessor 可以处理/注入(inject)它。

考虑循环依赖。将代码段中的 @Configuration 类与以下类的附加 @ComponentScan

结合使用
@Component
class AccountRepository {
public AccountRepository(Foo foo) {}
}
@Component
class Foo {
public Foo(TransferService ts) {}
}

@Configuration bean 被初始化。 AutowiredAnnotationBeanPostProcessor 开始处理 accountRepository 字段。它寻找一个 AccountRepository bean 并尝试初始化它。它需要一个 Foo bean 来实例化它(用于构造函数注入(inject))。它寻找一个 Foo bean 并尝试初始化它。它需要一个 TransferService bean 来实例化它(用于构造函数注入(inject))。它查找 TransferService bean 并找到 @Bean 工厂方法。它调用它。 accountRepository 尚未初始化,因此仍为 null。您可以通过在 @Bean 方法中放置一个断点并浏览堆栈跟踪来验证这一点。

您是否按照上面引述的建议使用了参数注入(inject)

Whenever possible, resort to parameter-based injection as in the example above.

Spring 会崩溃并警告你

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'accountRepository': Requested bean is currently in creation: Is there an unresolvable circular reference?


That's the workaround I ended up doing

我目前无法解释这一点。

关于java - 为什么@Configuration 类中的@Autowired 字段为空?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41111466/

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