三级缓存和依赖循环

40 阅读2分钟

一. 依赖循环

依赖循环的定义

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解决依赖循环的流程

image.png

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