Bean的三级缓存解决循环依赖


忘了就可以回顾一下黑马的:框架篇-51-循环依赖_一级缓存作用_哔哩哔哩_bilibili

主要用于解决 Bean 的循环依赖和重复创建问题

Bean 的三级缓存是什么

三级缓存分别如下:

  1. singletonObjects: 当一个 Bean 被完全创建和初始化后,会被放入 singletonObjects 单例池缓存中。这个缓存存储的是完全初始化的 Bean 实例
  2. earlySingleObjects:存放还没走完生命周期的 Bean,也就是半成品 Bean 对象。
  3. singletonFactories: 存储创建 Bean 的 ObjectFactory 工厂类对象的缓存。

为什么要加上三级缓存(怎么解决缓存依赖问题)

从三级缓存的作用以及不足讲解。

一级缓存

singletonObjects : 单例池缓存。

作用:Bean 对象只会在这里保存一份对象,避免 Bean 重复创建,实现单例。

缺点不能解决循环依赖问题


在加载 A 的过程中想要使用 B 对象,结果单例池不存在,则需要先去创建 B 对象,然而 B 类的内部也需要 A,则会等 A 创建成功才能使用 A 对象,才能完成 B 的创建。造成了彼此等待的情况,也就是循环依赖。

二级缓存

earlySingleObjects : 二级缓存

作用:存放半成品的 Bean 对象,循环依赖的另一个对象可以通过二级缓存得到半成品对象完成实例化,然后再返回给半成品对象完成实例化。

解决循环依赖的过程:

A 的对象创建,实例化的时候先把半成品的放到二级缓存,然后需要 B,先查单例池和二级缓存,发现没有 B 对象,然后就去创建 B,B 发现缓存中有半成品的 A 对象,就拿来进行 B 的创建,创建并初始化完成得到完全体 B 对象,然后返回给 A 进行下面的创建,就解决了循环依赖问题。

缺点:虽然看样子解决了问题,但是如果在有代理对象要创建的情况下,还是会有问题。

通过代理给对象进行功能增强,需要创建代理对象,如果不使用三级缓存,会导致代理功能失效。比如下图:

可以看到传递给 B 的 A 对象不是完整的被代理增强过的,而是半成品的 A 对象,这样 A 的增强就失效了。

三级缓存

singletonFactories :存放创建 Bean 的 ObjectFactory 对象。

作用完全解决循环依赖的问题。

解决过程如下:

解决方法实际上就是通过三级缓存存储 ObjectFactory 对象(这个对象可以创建某个对象的代理对象或普通对象),当创建 A 对象的时候会先把它的 ObjectFactory 比如 Fa 对象放进三级缓存中,然后查询 B,发现没有 B,就去创建 B,同样放进一个 Fb 对象到缓存,然后发现需要 A 的对象,结果找到了 A 的工厂对象 Fa,这个工厂对象就看你是不是发生了循环依赖,如果是就会创建代理对象给 B,否则就给普通对象。剩下的过程略。

所以使用这种三级缓存就可以解决代理失效问题,完全解决循环依赖问题。


文章作者: KTpro
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 KTpro !
  目录