为什么@Configuration类中的@Autowired字段为空? [英] Why is an @Autowired field within a @Configuration class null?

查看:1651
本文介绍了为什么@Configuration类中的@Autowired字段为空?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是来自

This is an example from the Spring documentation, section 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的执行顺序有关的事情可以保证在可能调用@Bean方法之前先处理@Autowired变量?什么是加工订单?哪种情况会导致Spring无法按顺序处理这些问题?

My question is: why must it happen that accountRepository is created before it's used by new TransferServiceImpl()? Offhand, I don't see how Spring could know that the second one depends on the first one being set up (unless it goes through the transferService() bytecode). Is it because something about the order in which Spring does things guarantees that the @Autowired variable is processed before the @Bean method could possibly be called? What is the processing order? What kinds of circumstances could cause Spring to process these out of order?

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

The reason I'm asking is that I have a case where something like this isn't working, i.e. the new is being executed with a null argument. Either the @Autowired variable is being set up too late, or it isn't set up at all (my guess is the latter, based on some log4j.logger.org.springframework.beans debugging output, but I'm not sure). The situation is of course much more complex--it's a largish application, and there are a few more @Autowired and @Bean definitions in the configuration class. Using @DependsOn hasn't helped. It will take a lot of time to narrow down the problem by deleting code until I can get a minimal example, but I wanted to see if I could get some insight into the problem by learning more details about how Spring processes things, before starting down the difficult code reduction path.

推荐答案

为什么在使用accountRepository之前必须发生这种情况 通过新的TransferServiceImpl()?

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

不是. accountRepository可能被视为null.

摘录自

确保以这种方式注入的依赖项属于 仅最简单的一种. @Configuration类的处理很早 在上下文的初始化过程中,并强制依赖 以这种方式注入可能会导致意外的早期初始化. 只要有可能,请像在 上面的例子.

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.

还要特别注意BeanPostProcessor 和 通过@BeanBeanFactoryPostProcessor定义.那些通常应该 被声明为static @Bean方法,而不触发实例化 其包含的配置类.否则,@Autowired@Value不适用于配置类本身,因为它正在 作为一个bean实例创建得太早了.

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.这样,它将由所有已注册的

In summary, a Configuration class will end up being just another bean in the application context. As such, it will be processed by all registered BeanPostProcessor beans.

@Autowired AutowiredAnnotationBeanPostProcessor .大概您正在使用AnnotationConfigApplicationContext,它会自动注册一个.

@Autowired is processed by AutowiredAnnotationBeanPostProcessor. Presumably, you're using AnnotationConfigApplicationContext which registers one automatically.

在您的示例中,此后是不完整的

In your example, which is incomplete since

...但要确定自动装配的Bean定义的确切位置 声明仍然有点模棱两可

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

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

However, we can assume some other configuration provided a bean definition for a AccountRepository bean. Once the application context instantiates the ServiceConfig bean, it can then post process it and inject @Autowired targets.

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

The only reason an @Autowired target could be null in a @Configuration bean instance is that you tried to read it before an AutowiredAnnotationBeanPostProcessor could process/inject it.

考虑循环依赖.在代码段中加入@Configuration类别,并添加以下其他@ComponentScan类别

Consider a circular dependency. Take the @Configuration class in your snippet with an additional @ComponentScan of the following classes

@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方法中放置一个断点并浏览堆栈跟踪来验证这一点.

The @Configuration bean get initialized. AutowiredAnnotationBeanPostProcessor kicks off to process the accountRepository field. It looks for an AccountRepository bean and tries to initialize it. It needs a Foo bean to instantiate it (for constructor injection). It looks for a Foo bean and tries to initialize it. It needs a TransferService bean to instantiate it (for constructor injection). It looks for a TransferService bean and finds the @Bean factory method. It invokes it. The accountRepository hasn't been initialized yet, so remains null. You can verify this by putting a breakpoint in the @Bean method and browsing the stack trace.

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

Had you used a parameter injection as suggested in the quote above

只要有可能,请像上面的示例中那样使用基于参数的注入.

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

春天会坠毁并警告您

起因: org.springframework.beans.factory.BeanCurrentlyInCreationException: 创建名称为'accountRepository'的bean时出错:请求的bean是 当前正在创建中:是否有无法解决的循环引用?

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

我目前无法解释.

这篇关于为什么@Configuration类中的@Autowired字段为空?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆