一、什么是循环依赖循环依赖其实就是循环引用,也就是两个或者两个以上的 Bean 互相持有对方,最终形成闭环 。比如A依赖于B,B依赖于C,C又依赖于A 。
文章插图
注意,这里不是函数的循环调用,是对象的相互依赖关系 。循环调用其实就是一个死循环,除非有终结条件 。
Spring中循环依赖场景有:
- 构造器的循环依赖(构造器注入)
- Field 属性的循环依赖(set注入)
二、循环依赖处理机制
- 单例 bean 构造器参数循环依赖(无法解决)
- prototype 原型 bean循环依赖(无法解决)
AbstractBeanFactory.doGetBean()方法:
文章插图
在获取bean之前如果这个原型bean正在被创建则直接抛出异常 。原型bean在创建之前会进行标记这个beanName正在被创建,等创建结束之后会删除标记 。
文章插图
总结:Spring 不支持原型 bean 的循环依赖 。
单例bean通过setXxx或者@Autowired进行循环依赖
Spring 的循环依赖的理论依据基于 JAVA 的引用传递,当获得对象的引用时,对象的属性是可以延后设置的,但是构造器必须是在获取引用之前 。
Spring通过setXxx或者@Autowired方法解决循环依赖其实是通过提前暴露一个ObjectFactory对象来完成的,简单来说ClassA在调用构造器完成对象初始化之后,在调用ClassA的setClassB方法之前就把ClassA实例化的对象通过ObjectFactory提前暴露到Spring容器中 。
文章插图
- Spring容器初始化ClassA通过构造器初始化对象后提前暴露到Spring容器 。
- ClassA调用setClassB方法,Spring首先尝试从容器中获取ClassB,此时ClassB不存在Spring容器中 。
- Spring容器初始化ClassB,同时也会将ClassB提前暴露到Spring容器中 。
- classB调用setClassA方法,Spring从容器中获取ClassA,因为第一步中已经提前暴露了ClassA,因此可以获取到ClassA实例 。
- ClassA通过spring容器获取到ClassB,完成了对象初始化操作 。
- 这样ClassA和ClassB都完成了对象初始化操作,解决了循环依赖问题 。
【SpringIOC循环依赖问题】
推荐阅读
- 相对车辆内循环而言外循环使用更有技巧
- 如何检查前端项目中未使用的依赖包?
- 许多|大学生追求公务员并不是一种病态,但过度依赖公务员职业固然可怕
- 美甲|书名:《异世界商店街经营指南》by依赖糖分
- 为什么电脑总是自动重启(电脑开机无限循环重启)
- 花泽香菜为什么不笑了(花泽香菜恋爱循环)
- 一文了解什么是 Linux 上的包依赖
- 如何促进血液循环增强气血 如何促进血液循环
- 心智成长三阶段:依赖独立互赖……人心智成长的七个阶段
- 转笔教程 新手 简单 无限循环 转转笔新手教程慢速