Spring-如何解决循环依赖

Spring-如何解决循环依赖

什么是循环依赖

循环依赖其实就是循环引用,也就是两个或者两个以上的 Bean 互相持有对方,最终形成闭环。比如A 依赖于B,B依赖于C,C又依赖于A。

注意: 这里不是函数的循环调用,是对象的相互依赖关系。循环调用其实就是一个死循环,除非有终结 条件。

Spring中循环依赖场景有:

  • 构造器的循环依赖(构造器注入)
  • Field 属性的循环依赖(set注入)

其中,构造器的循环依赖问题无法解决,只能拋出 BeanCurrentlyInCreationException 异常,在解决
属性循环依赖时,spring采用的是提前暴露对象的方法。

spring循环依赖处理机制

  • 单例 bean 构造器参数循环依赖(无法解决)
    • 原因:构造参数注入时,对象还没有创建,无法获取对象引用
  • prototype 原型 bean循环依赖(无法解决)
    • 原因:多例模式下,Bean创建后就不归IOC容器管理,无法注入其他对象中
  • 单例bean通过setXxx或者@Autowired进行循环依赖

Spring 的循环依赖的理论依据基于 Java 的引用传递,当获得对象的引用时,对象的属性是可以延 后设置的,但是构造器必须是在获取引用之前。

Spring通过setXxx或者@Autowired方法解决循环依赖;

假设A依赖B,B依赖A:

  1. 新建A,将引用放入三级缓存中
  2. 发现A依赖B:
    1. 从一级缓存查询,没有
    2. 从二级缓存查询,没有
    3. 从三级缓存查询,没有
    4. 新建B,将B引用放入三级缓存中
      a. 发现依赖A
      b. 从一级缓存找,没有
      c. 从二级缓存找,没有
      d. 从三级缓存找到,返回注入
      e. 走B的剩余生命周期处理
    5. B新建完成,存入一级缓存(单例池)中
  3. A注入B完成
  4. A剩余生命周期处理完成,存入一级缓存中
    Spring-如何解决循环依赖

如果有三个或者四个循环引用,就一级一级初始化,都是从三级缓存中获取引用注入的;