2016-12-12 98 views
2

这是the Spring documentation一个例子,部分6.12.5:为什么@Configuration类中的@Autowired字段为空?

@Configuration 
public class ServiceConfig { 

    @Autowired 
    private AccountRepository accountRepository; 

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

} 

我的问题是:为什么一定要它发生它使用new TransferServiceImpl()之前accountRepository创建? Offhand,我没有看到Spring如何知道第二个依赖于第一个设置(除非它通过transferService()字节码)。是否这是因为Spring的某些操作确保@Autowired变量在可能调用@Bean方法之前得到处理?处理顺序是什么?什么样的情况可能导致Spring处理这些乱序?

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

+4

在这种情况下,它不能。相反,在您的'transferService' bean方法中注入'AccountRepository'作为参数。 –

+0

这就是我最终做的解决方法。你是说Spring文档中的例子被破坏了吗? – ajb

+0

@ajb请完整阅读6.12.5。您拥有的代码仅是示例代码。它提到了这种模糊性。 –

回答

4

为什么一定发生accountRepository创建它是由新TransferServiceImpl()使用 过吗?

它没有。 accountRepository可能被看作是null

documentation you linked(其更新版本)的说明

确保你注入这样的依赖关系是样只有 简单。 @Configuration在上下文初始化期间处理相当早的类 并且强制依赖到 这样注入可能会导致意外的早期初始化。 只要有可能,请使用上述示例中的 示例中的基于参数的喷射。

另外,是经由@Bean特别小心BeanPostProcessorBeanFactoryPostProcessor定义。这些应该通常应该被声明为static@Bean方法,而不触发其包含配置类的实例化 。否则,@Autowired@Value将不会在配置类本身上工作,因为它太早创建为bean实例 。

总之,一个Configuration类将最终成为应用程序上下文中的另一个bean。因此,它将由所有注册的BeanPostProcessor豆进行处理。

@AutowiredAutowiredAnnotationBeanPostProcessor处理。据推测,你使用的是AnnotationConfigApplicationContext,它自动注册一个。

在你的榜样,这是不完全的,因为

...但究竟确定在自动装配bean定义是 声明仍然有些模糊

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

的唯一原因,一个@Autowired目标可能是在@Configuration bean实例null是你的努力的AutowiredAnnotationBeanPostProcessor前阅读它可以处理/注入它。

考虑循环依赖。拿在片段中@Configuration类以下类

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

@Configuration豆怎么被初始化的额外@ComponentScanAutowiredAnnotationBeanPostProcessor开始处理accountRepository字段。它寻找一个AccountRepository bean并尝试初始化它。它需要一个Foo bean来实例化它(用于构造器注入)。它查找Foo bean并尝试初始化它。它需要一个TransferService bean来实例化它(对于构造函数注入)。它寻找一个TransferService bean并找到工厂方法@Bean。它调用它。 accountRepository还没有初始化,所以仍然null。您可以通过在@Bean方法中放置断点并浏览堆栈跟踪来验证此情况。

假如你使用的参数注入作为报价建议上述

只要有可能,诉诸基于参数的注射如上面的例子。

春会一直崩溃,并警告你

产生的原因:与名'accountRepository' 错误创建豆: org.springframework.beans.factory.BeanCurrentlyInCreationException请求bean是 目前在创作:有一个无法解决的循环引用?


这是我最后的解决办法做

我目前还不能解释这个问题。

相关问题