当前位置: 首页 > 知识库问答 >
问题:

为什么使用@Autowired不会导致循环依赖,但构造函数会自动关联?

姜旭
2023-03-14

我注意到我正在开发的应用程序中有一个奇怪的bug。在修改一个类时,我将一组属性移动到构造函数中进行自动连接,而不是使用字段注入,然而,由于循环依赖关系,这导致我在启动时出错。下面是导致错误的依赖关系的分解:

  • 我正在尝试在TargetClass的内部使用ServiceA
  • 服务A通过其构造函数注入了服务B
  • 通过现场注入,服务B已注入服务C
  • 通过现场注入,ServiceC已注入TargetClass

我正在寻找重构的方法,或者尝试将一些逻辑转移到更好的地方,所以我删除了这个循环依赖,然而,我很好奇为什么两种不同的注入服务的方法会导致两种不同的结果:

如果我通过字段注入来注入ServiceA,只需在字段上使用Autowired,我的应用程序就可以正常启动。然而,如果我切换到使用构造函数注入的TargetClass,我将得到一个关于循环依赖的错误。

Spring处理两种类型的注入的方式有什么不同,这两种注入会导致一种在这种情况下失败,另一种工作?

共有1个答案

夹谷浩博
2023-03-14

现场注入工作如下

ServiceA serviceA = new ServiceA();
ServiceB serviceB = new ServiceB();
serviceA.serviceB = serviceB;
serviceB.serviceA = serviceA;

构造函数注入失败,因为

ServiceA serviceA = new ServiceA(????); // Cannot inject serviceB because to create serviceB I need serviceA which is being constructed

不过,即使使用构造函数,也有办法使用循环deps。

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应用程序。当我重构一些loc时,我注意到以下行为: 事实上,注入工作正常: 当我尝试使用构造函数注入时,环境为空,我的应用程序告诉我,由于循环引用,它无法创建配置bean: 在堆栈的某个地方: 原因:org.springframework.beans.factory.Bean货币InCreationException:创建名为appConfig的bean时出错:请求的

  • 请问上述代码的第70行换成第71行注释的内容时,为什么会造成死循环。 题目: https://www.acwing.com/problem/content/174/

  • 我似乎在实现中偶然发现了一些有趣的东西,但我不能把头绕过去。下面是一些代码,说明了我的意思: 其思想是,如果您创建一个,如下所示: 并在(中保留了所有元素)的内部查看它将报告的内容。因此,您添加了一个元素--您得到了9个未使用的额外插槽。 另一方面,如果您这样做: 添加一个元素,保留的空间仅限于该元素,仅此而已。 在内部,这通过两个字段实现: 我们将它与EMPTY_ELEMENTDATA区分开来,

  • 问题内容: 当我尝试将$ http注入到覆盖的工厂中时,出现错误: 未捕获的错误:[$ injector:cdep]找到循环依赖项:$ http <-$ exceptionHandler <-$ rootScope 任何想法如何解决?如果我使用[]注入,则$ http是未定义的 编辑 ___ _ ___ ___ _ 根据下面的答案,我尝试了: 但我仍然收到循环错误: 未捕获的错误:[$ injec

  • 旧代码: 新代码: 这里我得到了: 组织。springframework。豆。工厂BeanCurrentlyIncremationException:创建名为“someFactory”的bean时出错:请求的bean当前正在创建中:是否存在无法解析的循环引用? 当通过构造函数自动连接时,Spring是否存在一些问题?

  • 我有一个看起来很简单的问题,但由于某种原因我无法绕过它。基本上我的程序正在导致一个无限循环,我不知道为什么。 下面是我陷入的特定循环: 当我运行它时,它总是问我输入列#。我给它一个数字,它接受这个数字,$response变为True,但while循环继续运行,就好像<code>的$response</code>为false一样。我是Perl新手,所以可能我遗漏了一些东西,但是($response=