Spring 循环依赖问题(三级缓存)

发布于:2022-12-15 ⋅ 阅读:(264) ⋅ 点赞:(0)

我们常常会说“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)

网站公告

今日签到

点亮在社区的每一天
去签到