我们常常会说“Spring是通过三级缓存来解决循环依赖问题的”,那么
- 所有的循环依赖问题都解决了吗?
- 为什么是三级缓存?
- 每级缓存分别存的是什么?
带着上面几个问题分析一下整个循环依赖的过程。
现在有两个类AService和BService,其中AService依赖BService,BService也依赖AService。
@Component
public class AService {
@Autowired
private BService bService;
}
@Component
public class BService {
@Autowired
private AService aService;
}
我们假定AService Bean先创建,此时
单例Bean之间的循环依赖过程
上图就是整个Spring单例Bean的循环依赖过程,该流程只针对属性注入和sertter方法注入。对于构造方法循环依赖Spring并没有解决,会报错。相当于存入三级缓存的半成品的Bean都实例化不出来(三级缓存中提前AOP函数其中一个参数是刚实例化完的半成品AService对象)。
原型(多例)Bean之间的循环依赖
Spring也没有解决原型Bean之间的循环依赖问题,如果AService和BService都是原型Bean会直接报错。
大致分析一下其循环依赖过程,对于原型Bean来说每次依赖都会创建一个新的对象,整个过程就会变成 AService ---> 创建BService ---> 创建AService ---> 又创建个新的BService ......无限循环下去。但是其中只要有一个Bean是单例的,就可以正常循环依赖,无非就是多绕几次。
最后回答一下文章开头的问题
- 所有的循环依赖问题都解决了吗?
- 没有,原型Bean以及单例Bean之间构造方法循环依赖没有解决
- 为什么是三级缓存?
- 其实只有【二级缓存】也能解决循环依赖问题,比如在存入三级缓存的位置把需要AOP就提前AOP存入【二级缓存】不需要AOP的把半成品AService Bean也存入【二级缓存】,在BService依赖AService的时候直接从【二级缓存】取出进行注入。但是这样的话所有需要AOP的Bean都要提前AOP了,这显然不符合Bean生命周期流程(AOP是在初始化后进行的)。Spring是在BService注入AService判断出AService正在创建中(即发生了循环依赖)时会存入二级缓存,AService需要AOP就提前AOP存入代理对象,不需要AOP就存入半成品的AService Bean,那么第三级缓存就是必要的,不然用什么来提前AOP呢?
- 每级缓存分别存的是什么?
- 一级缓存:单例池
- 二级缓存:要么是原始的半成品Bean,要么是提前AOP之后的Bean(是有存在循环依赖时才会存)
- 三级缓存:工厂方法(判断需要AOP吗,需要则进行AOP返回AOP后的代理对象,不需要则返回Bean)