什么是循环依赖
假设A,B都是Spring容器中的Bean, 其中A依赖于B,而B中也依赖于A,这样就会出现循环依赖.
构造器注入循环依赖Spring没有解决.
set注入循环依赖,A中注入了B, B中也注入了A, Spring解决了. 我们主要讲Spring是如何解决set注入循环依赖的.
Spring三级缓存解决循环依赖问题
三级缓存就是Spring通过三个map解决循环依赖问题.
一级缓存(singletonObjects): 用于存放完整的bean,已经初始化成功完成赋值的bean.
二级缓存(earlySingletonObjects):用于存放半成品的bean, 创建完成但属性没有完成初始化的bean.
三级缓存(singletonFactories):用于存放对象工厂, 对象工厂用于创建半成品bean,当bean被AOP增强时存放的是Lambda表达式, 返回代理对象, 没有被AOP增强时,直接创建, 返回实例.
三级缓存通过工厂的延迟执行特性,确保在真的需要时生成代理对象,而不是提前生成,这样就可以解决循环依赖,又可以保证aop的正确性。
例:A中注入了B, B中注入了A,出现循环依赖.
Spring首先会检查是否有出现循环依赖问题, 发现循环依赖问题,首先会创建A实例,将一个能够创建A对象的对象工厂存入三级缓存, 填充A属性时需要创建B对象, 这时会去创建B对象, 直接创建B对象存入二级缓存, B对象填充属性时需要A对象,这时会去一级缓存中找 没有, 去二级缓存中找 没有, 去三级缓存 通过对象工厂创建A的实例,把A实例存入二级缓存, 将这个实例赋值给B对象的A字段. 此时将创建好的B存入一级缓存,删除二级缓存中的B. 继续给A填充B字段, 去一级缓存找, 找到B对象存入A对象, A对象也完成了创建, 这时将A对象存入一级缓存,删除二级缓存中的A对象, 这是A和B对象都完成了初始化, 并且都存入了一级缓存.