请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

spring 三级缓存问题

在spring 单例模式下解决循环依赖用到三级缓存,我想请问一哥,二级缓存能解决问题吗?为什么需要三级,这里面还是没有太明白。

正在回答

1回答

阿斯拉菲你好:

    我们先来解读下什么是循环依赖:简单地说,就是循环引用,两个或者多个 bean 相互之间的持有对方,形成一个闭环。如,A 依赖 B,B 又依赖 A,它们之间形成了循环依赖,又或者是 A 依赖 B,B 依赖 C,C 又依赖 A。可以用一张经典的图(图片来自于网络)描述这种依赖关系。

    Spring 能够轻松的解决属性的循环依赖是用到了三级缓存,下面,我们来看看这三级缓存的定义:

/**一级缓存,用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/**三级缓存 存放 bean 工厂对象,用于解决循环依赖*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/**二级缓存 存放原始的 bean 对象(尚未填充属性),用于解决循环依赖*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

    (1)一级缓存:singletonObjects,存放完全实例化属性赋值完成的Bean,直接可以使用

    (2)二级缓存:earlySingletonObjects,存放早期Bean的引用,尚未属性装配的Bean

    (3)三级缓存:singletonFactories,三级缓存,存放实例化完成的Bean工厂

    所以,其实你也可以看出来了,三级缓存是解决循环依赖的重中之重:因为 Spring 在 Bean 的创建过程中,首先就会从尝试从缓存中获取,如果没有获取到,就会走到 Bean 的创建过程。如果存在循环依赖,则会利用三级缓存的策略 逐步递进式的初始化各个 Bean,最终完成整体的初始化。但是,需要注意,对于构造函数注入方式造成的循环依赖,Spring 是解决不了的。

    那么,到这里,基本上也就说明了为什么需要三级缓存,以及三级缓存是怎么解决循环依赖的了。最后,再来看一张更具体的调用关系图,A 与 B 之间存在循环依赖,但是怎样完成初始化。

    不过,我的建议是不要盲目的去看 Spring 源码,知道其含义和原理就可以,源码非常的复杂而且很长,读起来会比较吃力。


    我是勤一,致力于将这门课程的问答区打造为 Java 知识体系知识库,Java 知识体系 BBS!共同建造、维护这门课程,我需要每一个你!


4 回复 有任何疑惑可以回复我~
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信