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:
- 新建A,将引用放入三级缓存中
- 发现A依赖B:
- 从一级缓存查询,没有
- 从二级缓存查询,没有
- 从三级缓存查询,没有
- 新建B,将B引用放入三级缓存中
a. 发现依赖A
b. 从一级缓存找,没有
c. 从二级缓存找,没有
d. 从三级缓存找到,返回注入
e. 走B的剩余生命周期处理 - B新建完成,存入一级缓存(单例池)中
- A注入B完成
- A剩余生命周期处理完成,存入一级缓存中
如果有三个或者四个循环引用,就一级一级初始化,都是从三级缓存中获取引用注入的;