循环依赖整体流程图:
循环依赖步骤:
1、A 类无参构造函数实例化后,设置三级缓存
2、A 类 populateBean 进行依赖注入,这里触发了 B 类属性的 getBean 操作
3、B 类无参构造函数实例化后,设置三级缓存
4、B 类 populateBean 进行依赖注入,这里触发了 A 类属性的 getBean 操作
5、A 类之前正在实例化,singletonsCurrentlyInCreation 集合中有已经有这个 A 类了,三级缓存里面也有了,所以这时候是从三级缓存中拿到的提前暴露的A 实例,该实例还没有进行 B 类属性的依赖注入的,B 类属性为空。
6、B 类拿到了 A 的提前暴露实例注入到 A 类属性中了
7、B 类实例化已经完成,B 类的实例化是由 A 类实例化中 B 属性的依赖注入触发的 getBean 操作进行的,现在 B 已经实例化,所以 A 类中 B 属性就可以完成依赖注入了,这时候 A 类 B 属性已经有值了
8、B 类 A 属性指向的就是 A 类实例堆空间,所以这时候 B 类 A 属性也会有值了。
1、什么是bean循环依赖?
在进行getBean的时候,A对象中去依赖B对象,而B对象又依赖A对象,A、B对象都不能完成实例化,出现了循环依赖。就会出现死循环,最终导致内存溢出的错误。代码案例如下: