Spring 为什么要三级缓存,二级缓存不行吗?

您所在的位置:网站首页 世界的第三级是什么 Spring 为什么要三级缓存,二级缓存不行吗?

Spring 为什么要三级缓存,二级缓存不行吗?

2024-03-23 11:20| 来源: 网络整理| 查看: 265

Spring 设计了三级缓存来解决循环依赖问题。

singletonObjects 一级缓存,用于保存实例化、注入、初始化完成的 bean 实例earlySingletonObjects 二级缓存,用于保存实例化完成、还没依赖注入的 bean 实例singletonFactories 三级缓存,用于保存 bean 创建工厂,以便于后面扩展有机会创建代理对象。

三级缓存的核心思想,就是把 Bean 的实例化和依赖注入进行分离。

举个例子,testService1、testService2 互相依赖,spring 是如何解决循环依赖的: 在这里插入图片描述

图片来自 spring为什么使用三级缓存而不是两级? - 知乎 (zhihu.com)

为什么要三级缓存,二级缓存不行?

其实也行,并不是说二级缓存如果存在aop的话就无法将代理对象注入的问题,本质应该说是初始spring是没有解决循环引用问题的,设计原则是 bean 实例化、属性设置、初始化之后再生成aop对象,但是为了解决循环依赖但又尽量不打破这个设计原则的情况下,使用了存储了函数式接口 ObjectFactory 的第三级缓存。

如果使用二级缓存的话,可以将 AOP 代理工作提前到 提前暴露实例 的阶段执行; 也就是说所有的 bean 在创建过程中就直接生成代理对象;但是这样的话,就和 Spring AOP 的设计原则相驳,AOP 的实现需要与 bean 的正常生命周期的创建分离;

比如下面是一个二级缓存,对应三级缓存中的前两级缓存。现在有两个类 A、B 互相依赖,且 B 需要 AOP 代理增强。

步骤:

A 从一级缓存中取不到实例,创建实例 A,添加进二级缓存A 进行依赖注入,要注入 BB 从一级缓存中取不到实例,直接创建代理类 B 的实例,添加进二级缓存代理 B 进行依赖注入,要注入 AA 从二级缓存中获取到代理 B,A 依赖注入完成A 初始化完成,A 添加到一级缓存,删除二级缓存中的 A代理 B 从一级缓存中获取到 A,代理 B 依赖注入成功代理 B 初始化完成,代理 B 添加到一级缓存,删除二级缓存中的代理 B

在这里插入图片描述

那怎样才能让 AOP 的实现需要与bean的正常生命周期的创建分离?

使用第三级缓存封装一个函数式接口对象到缓存中, 发生循环依赖时,触发代理类的生成。也就是依赖注入前,发现依赖的对象是需要代理增强的,从第三级缓存中获取代理类存入第二级缓存,然后继续完成依赖注入,把代理增强和 bean 生命周期的创建分离开。

还是上面的例子,如果改成三级缓存步骤如下:

A 从一级缓存和二级缓存中取不到实例,创建 A 工厂,添加进三级缓存A 进行依赖注入,要注入 BB 从一级缓存和二级缓存中取不到实例,创建 B 工厂,添加进三级缓存B 进行依赖注入,要注入 AA 发现要注入的 B 需要代理增强,从三级缓存中获取到 B 工厂,B 工厂创建代理 B 实例,并把 代理 B 存入二级缓存,A 依赖注入完成A 初始化完成,A 添加到一级缓存,删除二级缓存中的 A 工厂代理 B 从一级缓存中获取到 A,代理 B 依赖注入成功代理 B 初始化完成,代理 B 添加到一级缓存,删除二级缓存中的代理 B 和 三级缓存中的 B 工厂

当然这都是理论,要验证还需要代码的实践,这位老哥对源码进行了修改,证实了二级缓存下,Spring 的确是可以运行正常。👇 【超级干货】为什么spring一定要弄个三级缓存?



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3