spring通过三级缓存解决循环依赖
三级缓存
- 一级缓存:singletonObjects,放的是完整的bean【创建完了,属性也完成赋值的】
- 二级缓存:earlySingletonObjects,放的是半成品的bean【创建完了,属性未完成初始化】
- 三级缓存:singletonFactories,三级缓存放lambda表达式,来完成代理对象的创建
循环依赖时,bean初始化全过程
- 创建A,发现需要B。创建B,发现需要A,这个时候就出现了循环依赖
- getBean(a):创建A ---> 先创建出A的对象 ---> 构造一个A代理对象的工厂的对象放入到三级缓存
- getBean(b):A需要注入B ---> 容器中没有B,去创建B ---> 逐层从一级缓存开始查找,直到三级缓存为止 ---> 先创建B的对象,放入二级缓存 ---> 发现需要A,则去获取A的时候,发现在三级缓存中有创建A对象的工厂,于是使用工厂创建A对象。将创建出的A对象放入到二级缓存,移除三级缓存的工厂对象。---> B需要A【但A现在是一个有地址但不完整的对象,可以赋值了】,于是B就完全初始化成功成一个完整的Bean,把B放入到一级缓存。
- 回到A调用getBean(b)的方法,继续造A,A再从一级缓存去获取B,有 ----> A也初始化成一个完成的bean ---> 那么把二级缓存的A放入到一缓存,删除二级缓存中的A
你的项目中有没有循环依赖问题?怎么解决?
答:实际开发中,尽量手动去避免循环依赖的产生。如 AService 需要调用 BService,而 BService 需要调用 AService,把BService要调用AService的方法提取到一个新的Service,如 CService,BService 注入 CService