3. 原理深度解读3.1 什么要有 3 级缓存 ?这是一道非常经典的面试题,前面已经告诉大家详细的执行流程,包括源码解读,但是没有告诉大家为什么要用 3 级缓存?
这里是重点!敲黑板?。。?
我们先说“一级缓存”的作用 , 变量命名为 singletonObjects,结构是 Map<String, Object>,它就是一个单例池 , 将初始化好的对象放到里面,给其它线程使用,如果没有第一级缓存,程序不能保证 Spring 的单例属性 。
“二级缓存”先放放,我们直接看“三级缓存”的作用,变量命名为 singletonFactories,结构是 Map<String, ObjectFactory<?>>,Map 的 Value 是一个对象的代理工厂,所以“三级缓存”的作用,其实就是用来存放对象的代理工厂 。
那这个对象的代理工厂有什么作用呢,我先给出答案,它的主要作用是存放半成品的单例 Bean,目的是为了“打破循环”,可能大家还是不太懂,这里我再稍微解释一下 。
我们回到文章开头的例子,创建 A 对象时 , 会把实例化的 A 对象存入“三级缓存”,这个 A 其实是个半成品,因为没有完成依赖属性 B 的注入,所以后面当初始化 B 时,B 又要去找 A,这时就需要从“三级缓存”中拿到这个半成品的 A(这里描述 , 其实也不完全准确,因为不是直接拿,为了让大家好理解,我就先这样描述),打破循环 。
那我再问一个问题 , 为什么“三级缓存”不直接存半成品的 A,而是要存一个代理工厂呢 ?答案是因为 AOP 。
在解释这个问题前 , 我们看一下这个代理工厂的源码,让大家有一个更清晰的认识 。
直接找到创建 A 对象时,把实例化的 A 对象存入“三级缓存”的代码,直接用前面的两幅截图 。
文章插图
图片
文章插图
图片
下面我们主要看这个对象工厂是如何得到的,进入 getEarlyBeanReference() 方法 。
文章插图
图片
文章插图
图片
文章插图
文章插图
图片
最后一幅图太重要了 , 我们知道这个对象工厂的作用:
- 如果 A 有 AOP,就创建一个代理对象;
- 如果 A 没有 AOP,就返回原对象 。
我再问一个问题,为什么要这样设计呢?把二级缓存干掉不行么 ?我们继续往下看 。
3.2 能干掉第 2 级缓存么 ?
@Servicepublic class A {@Autowiredprivate B b;@Autowiredprivate C c;public void test1() {}}@Servicepublic class B {@Autowiredprivate A a;public void test2() {}}@Servicepublic class C {@Autowiredprivate A a;public void test3() {}}
根据上面的套娃逻辑,A 需要找 B 和 C,但是 B 需要找 A,C 也需要找 A 。假如 A 需要进行 AOP,因为代理对象每次都是生成不同的对象,如果干掉第二级缓存,只有第一、三级缓存:
- B 找到 A 时 , 直接通过三级缓存的工厂的代理对象,生成对象 A1 。
- C 找到 A 时,直接通过三级缓存的工厂的代理对象,生成对象 A2 。
所以“二级缓存”的目的是为了避免因为 AOP 创建多个对象,其中存储的是半成品的 AOP 的单例 bean 。
如果没有 AOP 的话,我们其实只要 1、3 级缓存,就可以满足要求 。
4. 写在最后我们再回顾一下 3 级缓存的作用:
- 一级缓存:为“Spring 的单例属性”而生,就是个单例池,用来存放已经初始化完成的单例 Bean;
推荐阅读
- API接口脱敏:如何安全地处理敏感数据?
- 详细解析BIOS如何清除硬盘数据
- 如何有效设置和管理电脑用户账户及权限
- 如何快速提升电脑启动速度?这几种方法简单又实用!
- 如何为父母办理异地就医备案?常见问题解答来了
- 火龙果该如何保存 火龙果怎么保鲜
- 鱼缸水浑浊原因和解决方案 底滤鱼缸水浑浊原因和解决方案
- 虎年属猪人的运势如何 虎年属猪人的运势如何呢
- 42岁香港女星自曝:因私生活不协调离婚,解决不了生儿育女的问题
- 电商的运营模式是什么 电商运营模式如何运作的