spring - 为什么使用 @Autowired 不会导致循环依赖,但 Autowiring 构造函数却会导致循环依赖?

标签 spring spring-boot dependency-injection

我注意到我正在开发的应用程序中有一些奇怪的错误。在修改类时,我移动了一堆要在构造函数中 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/

相关文章:

android - 尝试使用 koin 但在 android 上无法正常工作

java - Spring Boot 配置和使用两个数据源

java - 从 Spring Data JPA 1.4 升级到 1.8 后,如何解决自定义 JpaRepositoryFactory 中的编译错误?

spring boot 数据 cassandra 响应式(Reactive) JmxReporter 问题

java - 如何禁用Spring Boot的自动提交?

java - 多个 Java 对象到单个端点

java - 将依赖注入(inject)与 Apache Commons IO 结合使用

java - Spring用非主bean覆盖主bean

spring - 将 HTML5 占位符属性添加到 Spring 3.0 表单输入元素

spring - 在spring数据jpa中动态实现数据源