为什么@Configuration类中的@Autowired字段为空? [英] Why is an @Autowired field within a @Configuration class null?
问题描述
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 newTransferServiceImpl()
?
不是. accountRepository
可能被视为null
.
摘录自
确保以这种方式注入的依赖项属于
仅最简单的一种. Make sure that the dependencies you inject that way are of the
simplest kind only. 还要特别注意 Also, be particularly careful with 总而言之, In summary, a 在您的示例中,此后是不完整的 In your example, which is incomplete since ...但要确定自动装配的Bean定义的确切位置
声明仍然有点模棱两可 ...but determining exactly where the autowired bean definitions are
declared is still somewhat ambiguous 但是,我们可以假设其他配置为 However, we can assume some other configuration provided a bean definition for a 在 The only reason an 考虑循环依赖.在代码段中加入 Consider a circular dependency. Take the The 您是否已按照上面引文中的建议使用了参数注入 Had you used a parameter injection as suggested in the quote above 只要有可能,请像上面的示例中那样使用基于参数的注入. Whenever possible, resort to parameter-based injection as in the example above. 春天会坠毁并警告您 起因:
Caused by:
@Configuration
类的处理很早
在上下文的初始化过程中,并强制依赖
以这种方式注入可能会导致意外的早期初始化.
只要有可能,请像在
上面的例子.
@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
和
通过@Bean
的BeanFactoryPostProcessor
定义.那些通常应该
被声明为static
@Bean
方法,而不触发实例化
其包含的配置类.否则,@Autowired
和
@Value
不适用于配置类本身,因为它正在
作为一个bean实例创建得太早了.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.这样,它将由所有已注册的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.
AccountRepository
bean提供了bean定义.一旦应用程序上下文实例化了ServiceConfig
bean,它就可以对其进行后处理并注入@Autowired
目标.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
处理/注入它之前读取它.@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
类别@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
方法中放置一个断点并浏览堆栈跟踪来验证这一点.@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.
org.springframework.beans.factory.BeanCurrentlyInCreationException
:
创建名称为'accountRepository'
的bean时出错:请求的bean是
当前正在创建中:是否有无法解决的循环引用?
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屋!