+-
java – 为什么@Configuration类中的@Autowired字段为null?
这是 the Spring documentation第6.12.5节的一个例子:

@Configuration
public class ServiceConfig {

    @Autowired
    private AccountRepository accountRepository;

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

}

我的问题是:为什么必须在新的TransferServiceImpl()使用之前创建accountRepository?另外,我不知道Spring怎么知道第二个依赖于第一个被设置(除非它通过transferService()字节码).是因为关于Spring执行事务的顺序的某些事情保证在可能调用@Bean方法之前处理@Autowired变量?什么是处理订单?什么样的情况会导致Spring处理这些乱序?

我问的原因是我有一个这样的事情,这样的事情没有用,即新的正在使用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处理.

@Autowired由AutowiredAnnotationBeanPostProcessor处理.据推测,您正在使用AnnotationConfigApplicationContext,它自动注册一个.

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

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

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

@Autowired目标在@Configuration bean实例中可能为null的唯一原因是您在AutowiredAnnotationBeanPostProcessor处理/注入它之前尝试读取它.

考虑一个循环依赖.使用以下类的其他@ComponentScan获取代码段中的@Configuration类

@Component
class AccountRepository {
    public AccountRepository(Foo foo) {}
}
@Component
class Foo {
    public Foo(TransferService ts) {}
}

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

您是否使用了上面引用中建议的参数注入

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

春天会崩溃并警告你

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字段为null? - 乐贴网