我注意到我正在开发的应用程序中有一些奇怪的错误。在修改类时,我移动了一堆要在构造函数中 Autowiring 的属性,而不是使用字段注入(inject),但是,这导致我在启动时由于循环依赖而出现错误。以下是导致错误的依赖项的详细信息:
- 我正在尝试在
TargetClass
内部使用ServiceA
。 ServiceA
通过其构造函数注入(inject)了ServiceB
ServiceB
通过字段注入(inject)注入(inject)了ServiceC
ServiceC
通过字段注入(inject)注入(inject)了TargetClass
我正在研究重构它的方法,或者尝试将一些逻辑移动到更好的地方,以便消除这种循环依赖,但是,我很好奇为什么要使用两种不同的方法来注入(inject) ServiceA
导致两种不同的结果:
如果我通过字段注入(inject)注入(inject)ServiceA
,只需在字段上使用@Autowired
,我的应用程序就可以正常启动。但是,如果我将 TargetClass
切换为使用构造函数注入(inject),我将收到有关循环依赖项的错误。
Spring 处理两种类型的注入(inject)的方式有何不同,导致一种在这种情况下失败,而另一种则正常?
最佳答案
字段注入(inject)的工作方式类似于
ServiceA serviceA = new ServiceA();
ServiceB serviceB = new ServiceB();
serviceA.serviceB = serviceB;
serviceB.serviceA = serviceA;
构造函数注入(inject)失败,因为
ServiceA serviceA = new ServiceA(????); // Cannot inject serviceB because to create serviceB I need serviceA which is being constructed
不过,即使使用构造函数,也可以有循环依赖。
class ServiceA {
javax.inject.Provider<ServiceB> serviceBProvider;
@Autowired ServiceA(javax.inject.Provider<ServiceB> serviceBProvider) {
this.serviceBProvider = serviceBProvider;
}
void later() {
this.serviceBProvider.get().methodOfServiceB();
}
void methodOfServiceA() {}
}
class ServiceB {
javax.inject.Provider<ServiceA> serviceAProvider;
@Autowired ServiceB(javax.inject.Provider<ServiceA> serviceAProvider) {
this.serviceAProvider = serviceAProvider;
}
void later() {
this.serviceAProvider.get().methodOfServiceA();
}
void methodOfServiceB() {}
}
它之所以有效,是因为 Spring 就是这样做的
Provider<ServiceA> serviceAProvider = new Provider<>();
Provider<ServiceB> serviceBProvider = new Provider<>();
ServiceA serviceA = new ServiceA(serviceBProvider);
ServiceB serviceB = new ServiceB(serviceAProvider);
serviceAProvider.set(serviceA);
serviceBProvider.set(serviceB);
关于spring - 为什么使用 @Autowired 不会导致循环依赖,但 Autowiring 构造函数却会导致循环依赖?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61961758/