一. 依赖循环
依赖循环的定义
A,B都是spring容器的bean,A中有一个属性是B,B中有一个属性是A,A依赖于B,B同样依赖A,就会出现循环依赖问题
构造器注入循环依赖
构造器注入循环依赖,spring无法解决,因为构造器的创建实例和依赖注入无法分离
set注入依赖循环
spring通过三级缓存解决循环依赖问题
二. 三级缓存
spring通过三级缓存(三个map)解决
一级缓存
放的是完整的bean,创建完了,属性也完成赋值
singletonObejects
二级缓存
放的是半成品的bean,创建完,属性未完成初始化
earlySingletonObejects
三级缓存
放的是对象工厂ObejectFactory 用来创建半成品bena,如果非代理,直接创建
,如果代理,放lambda表达式.
三级缓存放lambda,来完成代理对象的创建
三. spring解决依赖循环的流程
1、创建A,发现需要B。创建B,发现需要A,这个时候就出现了循环依赖 2、getBean(a):创建A ---> 先把创建出A的对象 ---> 构造一个A代理对象的工厂的对象放入到三级缓存 3、getBean(b):A需要注入B ---> 容器中没有B,去创建B ---> 逐层从一级缓存开始查找,直到三级缓存为止 ---> 先创建B的对象,放入二级缓存 ---> 发现需要A,则去获取A的时候,发现在三级缓存中有创建A对象的工厂,于是使用工厂创建A对象。将创建出的A对象放入到二级缓存,移除三级缓存的工厂对象。---> B需要A【但A现在是一个有地址但不完整的对象,可以赋值了】,于是B就完全初始化成功成一个完整的Bean,把B放入到一级缓存。 4、回到A调用getBean(b)的方法,继续造A,A再从一级缓存去获取B,有 ----> A也初始化成一个完成的bean ---> 那么把二级缓存的A放入到一缓存,删除二级缓存中的A
四. 实际项目遇到解决的方法
第一种解决方法:
AService注入BMapper,Bservice注入AService
第二种解决方法:
把BService要调用AService的方法提取到一个新的Service,如 CService,BService 注入 CService