spring 循环依赖

在Spring框架中,循环依赖是指两个或多个Bean之间相互引用的情况。Spring容器在初始化这些Bean时可能会遇到问题,因为它们互相依赖对方来完成自己的初始化。循环依赖可以通过不同的方式发生,主要分为以下几种情况:

  1. 基于构造器的循环依赖

    • 当两个Bean通过构造器参数互相依赖时,Spring无法解决这种循环依赖。这是因为在创建一个对象之前,另一个对象必须已经完全构建并初始化完毕,而这在循环依赖的情况下是不可能实现的。
    • 解决方案:重构代码,避免构造器参数的循环依赖,或者使用setter方法注入。
  2. 基于setter方法的循环依赖

    • 当两个Bean通过setter方法互相依赖时,Spring可以通过部分初始化的方式来解决这种循环依赖。
    • Spring在处理循环依赖时会使用所谓的“三级缓存”,实际上是指Spring内部使用的几个Map结构:
      • singletonObjects:存放已经创建好的单例Bean实例。
      • earlySingletonObjects:存放部分初始化的单例Bean实例。
      • singletonFactories:存放Bean的工厂对象,即未完成初始化的Bean实例。
    • 当Spring创建一个Bean时,它会先检查是否已经存在于singletonObjects中。如果没有,则会创建一个新的Bean实例,并将其放在singletonFactories中。当需要注入其他Bean时,如果发现存在循环依赖,Spring会从singletonFactories中取出部分初始化的Bean实例来注入,而不是抛出异常。
  3. 基于字段注入的循环依赖

    • 字段注入本质上是基于setter方法的循环依赖的一种特殊情况。
    • 解决方案与基于setter方法的循环依赖相同。

下面是具体的步骤说明:

如何解决循环依赖

  1. 构造器注入

    • 不支持循环依赖。如果必须使用构造器注入,那么需要重新设计类的结构,避免循环依赖。
    • 示例代码:
      public class A {
          private B b;
      
          public A(B b) {
              this.b = b;
          }
      }
      
      public class B {
          private A a;
      
          public B(A a) {
              this.a = a;
          }
      }
      
    • 解决方案:重构代码,比如将依赖改为通过setter注入。
  2. setter注入

    • 支持循环依赖。Spring会创建Bean的实例,然后在初始化过程中逐步注入依赖。
    • 示例代码:
      public class A {
          private B b;
      
          public void setB(B b) {
              this.b = b;
          }
      }
      
      public class B {
          private A a;
      
          public void setA(A a) {
              this.a = a;
          }
      }
      
    • 解决方案:Spring会使用部分初始化的方式解决循环依赖。

总结

在大多数情况下,构造器注入是一个良好的实践,因为它可以确保Bean的不可变性和完整性。然而,在构造器注入不能解决问题时,可以考虑使用setter注入或其他方式来避免循环依赖。最好的做法是尽量避免设计中出现循环依赖,因为这通常是设计上的缺陷。如果确实需要依赖循环,那么应该考虑使用其他设计模式,例如观察者模式,来减少耦合度。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值