这是the Spring documentation第6.12.5节的一个例子:
@Configuration
public class ServiceConfig {
@Autowired
private AccountRepository accountRepository;
@Bean
public TransferService transferService() {
return new TransferServiceImpl(accountRepository);
}
}
我的问题是:为什么必须在accountRepository
使用new TransferServiceImpl()
之前创建transferService()
?另外,我不知道Spring怎么知道第二个依赖于第一个被设置(除非它通过@Autowired
字节码)。是因为关于Spring执行命令的顺序保证在@Bean
方法可能被调用之前处理new
变量?什么是处理订单?什么样的情况会导致Spring处理这些乱序?
我问的原因是我遇到过这样的情况,即null
正在使用@Autowired
参数执行。 log4j.logger.org.springframework.beans
变量设置得太晚,或者根本没有设置(我的猜测是后者,基于一些@Autowired
调试输出,但我不确定)。这种情况当然要复杂得多 - 这是一个很大的应用程序,配置类中还有一些@Bean
和@DependsOn
定义。使用{{1}}没有帮助。通过删除代码来缩小问题需要花费大量时间,直到我能得到一个最小的例子,但我想看看我是否可以通过了解有关Spring如何处理事情的更多细节来了解问题,然后再开始困难的代码减少路径。
答案 0 :(得分:5)
为什么必须在
accountRepository
使用之前创建TransferServiceImpl()
新accountRepository
?
它没有。 null
可能会被视为@Configuration
。
来自documentation you linked(其最新版本)
中的注释确保以这种方式注入的依赖项是 最简单的一种。
BeanPostProcessor
类很早就得到了处理 在初始化上下文和强制依赖 以这种方式注入可能会导致意外的早期初始化。 尽可能采用基于参数的注射方法 上面的例子。另外,请特别小心
BeanFactoryPostProcessor
和 通过@Bean
定义的static
。通常应该这样做 声明为@Bean
@Autowired
方法,不触发实例化 他们包含的配置类。否则,@Value
和Configuration
将无法在配置类本身上运行 太早创建为bean实例。
总之,@Autowired
类最终只是应用程序上下文中的另一个bean。因此,它将由所有已注册的BeanPostProcessor
bean处理。
AnnotationConfigApplicationContext
由AutowiredAnnotationBeanPostProcessor
处理。据推测,您正在使用AccountRepository
自动注册一个。
在您的示例中,自
以来不完整...但确定autowired bean定义的确切位置 声明仍然有些含糊不清
但是,我们可以假设一些其他配置为ServiceConfig
bean提供了bean定义。一旦应用程序上下文实例化@Autowired
bean,它就可以对其进行后处理并注入@Autowired
个目标。
在null
bean实例中@Configuration
目标可能是AutowiredAnnotationBeanPostProcessor
的唯一原因是您在@Configuration
处理/注入它之前尝试读取它。< / p>
考虑循环依赖。使用以下类别中的@ComponentScan
@Component
class AccountRepository {
public AccountRepository(Foo foo) {}
}
@Component
class Foo {
public Foo(TransferService ts) {}
}
课程
@Configuration
AutowiredAnnotationBeanPostProcessor
bean初始化。 accountRepository
开始处理AccountRepository
字段。它查找Foo
bean并尝试初始化它。它需要一个Foo
bean来实例化它(用于构造函数注入)。它查找TransferService
bean并尝试初始化它。它需要一个TransferService
bean来实例化它(用于构造函数注入)。它查找@Bean
bean并找到accountRepository
工厂方法。它调用它。 null
尚未初始化,因此仍为@Bean
。您可以通过在org.springframework.beans.factory.BeanCurrentlyInCreationException
方法中放置断点并浏览堆栈跟踪来验证这一点。
您是否使用了上面引用中建议的参数注入
尽可能采用基于参数的注入,如上例所示。
春天会崩溃并警告你
引起:
'accountRepository'
: 创建名为let formatter = DateFormatter() //2016-12-08 03:37:22 +0000 formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z" let now = Date() let dateString = formatter.string(from:now) NSLog("%@", dateString)
的bean时出错:请求的bean是 目前正在创作:是否存在无法解决的循环引用?
这是我最终做的解决方法
我目前无法解释这一点。
答案 1 :(得分:0)
我只是将accountRepository
移到方法的参数上,并使用@Autowired
进行注释以解决此问题。但我不知道为什么。我认为原因是关于Spring
的初始订单。
@Configuration
public class ServiceConfig {
@Bean
public TransferService transferService(@Autowired AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}