【Spring为什么使用三级缓存而不是两级解决循环依赖问题?】首先明确一点,Spring如果使用二级缓存也是完全能够解决代理bean的循环依赖问题的 。那Spring为什么要使用三级缓存的设计呢?在回答这个问题前我们先明确一些概念 。
Spring Bean相关的知识Spring Bean 的创建过程
文章插图
- 扫描xml或者注解获取BeanDefinition;
- 实例化bean:通过createBeanInstance方法创建bean的原始对象BeanWrApper;
- 注入bean的依赖:利用populateBean方法(本质是反射)注入bean的依赖属性;
- 初始化bean:调用initializeBean方法最终形成完整的bean对象;
Tips:二、三级缓存会在DI的过程中被删除,最终所有的Bean都会变成完整的bean并存入一级缓存中 。
- 三级缓存singletonFactories:在注入bean的依赖前存入,所有bean都会存入,循环依赖时会使用,代码如下:
/** Cache of singleton factories: bean name --> ObjectFactory */private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
- 二级缓存earlySingletonObjects:存放实例化的对象(可能是原始对象也可能是代理对象),代码如下:
/** Cache of early singleton objects: bean name --> bean instance */private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
- 一级缓存singletonObjects:用于存放完整的bean,代码如下:
/** Cache of singleton objects: bean name --> bean instance */private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
什么是循环依赖?循环依赖是指:Spring在初始化A的时候需要注入B,而初始化B的时候需要注入A,在Spring启动完成后这俩个对象都必须是完整的bean 。文章插图
循环依赖的场景有三种:
- 构造器循环依赖:Spring无法解决,因为bean创建的第一步就是通过构造器实例化,也就是说解决循环依赖的前提就是对象可以实例化并缓存,与JAVA死锁很像;
- prototype范围的依赖:该循环依赖Spring不可解决,prototype作用域的bean Spring不缓存,因此在依赖注入时无法获取到依赖的bean;
- setter循环依赖:该循环依赖是Spring推荐的方式,我们接下来就重点讲解这种方式;
@Servicepublic class A {// @Autowired也行@Resourceprivate B b;}@Servicepublic class B {// @Autowired也行@Resourceprivate A a;}
Spring 是如何利用多级缓存解决循环依赖的我们先抛开Spring的实现来做一次解决循环依赖的设计推演 。在没有缓存的情况下循环依赖的场景
文章插图
如图可以直接观察到,当没有缓存时,当发生循环依赖时直接死循环了,最终的结局就是StackOverflow或者OOM 。
增加一层缓存为了解决上面循环依赖的问题,我们加入一层缓存,缓存可以使用Map结构,key为beanName,value为对象实例 。如下如:
文章插图
从上图可以直观的看出,循环依赖的问题已经得到了完美解决,但是又有了一个新问题,这个缓存中的bean可能有已经创建完成的、正在创建中还没有注入依赖的,它们都掺杂在一起,我们如何保证Map里面的所有对象是完整的呢?一层缓存很显然不符合设计规范,也缺乏安全性与扩展性 。
二级缓存设计我们希望的是,明确已经构建完成的的Bean被放入到一个缓存中,创建中的bean在另外一个缓存中,于是就有了下面的结构:
推荐阅读
- Spring项目不要忽视这个超时配置,否则你的Http调用可能无法结束
- 如何正确的使用一条SQL删除重复数据
- 桥梁竹胶板 桥梁板上为什么有洞
- 鸿运当头为什么叶子蜷缩 鸿运当头叶子枯萎了怎么办
- 为什么十个化疗九个死 有癌症病人的家里阴气太重
- 最新香港电视剧tvb最新电视剧无厘头影视~无厘头大擂台玩了10多分去查询结果说没有q币为什么呢?难道是骗子
- 老天为什么不让圣人出山 圣人2021年几月出山
- 秋葵为什么咬不动
- 抚顺1000字文章 抚顺的作文
- 地狱人形师为什么救乱世狂刀?有关于霹雳布袋戏中的阴阳师和地狱人形师。?