IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring如何解决Bean的循环依赖? -> 正文阅读

[Java知识库]Spring如何解决Bean的循环依赖?

什么是循环依赖?

? ? ? ?在Spring中,对象不是new出来的,而是经历过一系列生命周期,通过依赖注入最终获得的。?循环依赖就是指多个bean之间的互相依赖,或者是自己注入自己的情况下,就比如A依赖于B,B依赖于C,C又依赖于A,这样就创造出了一个类似于先有鸡还是先有蛋的问题,造成系统崩溃。

????????

?Spring的循环依赖多发生在Spring容器注入的时候,且是单例。

如何解决循环依赖?

? ? ? ? 从根本问题出发,打破循环,不让Bean循环!

那么Spring是怎么样实现的呢?

? ? ? ? 首先,单例Bean的初始化完成过程为有三个阶段

? ? ? ? ①实例化;②属性赋值,③初始化

我们刚才所说的Spring容器注入主要发生在第①步初始化和②步属性赋值。所以我们要切入这个点去解决问题。

Spring解决单例循环依赖问题,使用了三级缓存

三级缓存:

/** Cache of singleton objects: bean name –> bean instance */
private final Map singletonObjects = new ConcurrentHashMap(256);
/** Cache of singleton factories: bean name –> ObjectFactory */
private final Map> singletonFactories = new HashMap>(16);
/** Cache of early singleton objects: bean name –> bean instance */
private final Map earlySingletonObjects = new HashMap(16);

每级缓存的大致意思作用

singletonFactories : 进入实例化阶段的单例对象工厂的cache (三级)

earlySingletonObjects :完成实例化但是尚未初始化的,提前暴光的单例对象的Cache (二级)

singletonObjects:完成初始化的单例对象的cache(一级)

我们创建Bean的时候,会先从cache缓存里找,这一部其实就是singletonObjects,它里面的犯法用到了三级缓存。

来看看他的主要方法

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    //判断该单例Bean是否正在创建
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            //是否允许从singletonFactories中通过getObject拿到对象
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    //将Bean放入earlySingletonObjects中,并从singletonFactories中移除,。
                    //从三级缓存过渡到了二级缓存
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

? ? ? ? Spring解决依赖循环主要就是靠这个三级缓存。

我们来分析一下

????????“A的setter依赖了B的实例对象,同时B的setter依赖了A的实例对象”这种循环依赖的情况。

????????A首先完成了初始化的第一步,并且将自己提前曝光到singletonFactories中,此时进行初始化的第二步,A发现自己依赖对象B,此时就尝试去get(B),发现B还没有被create,所以走B的create流程。

????????B在初始化第一步的时候发现自己依赖了对象A,于是尝试get(A),尝试一级缓存singletonObjects(没有,此时A还没初始化完全),尝试二级缓存earlySingletonObjects(还是没有),尝试三级缓存singletonFactories,由于A通过ObjectFactory将自己提前曝光了,所以B能够通过ObjectFactory.getObject拿到A对象(虽然A还没有初始化完全,但是也可以获取到,虽然用不了),B拿到A对象后顺利完成了初始化阶段1、2、3,完全初始化之后将自己放入到一级缓存singletonObjects中。

????????返回A中,A此时能拿到B的对象顺利完成自己的初始化阶段2、3,最终A也完成了初始化,进去了一级缓存singletonObjects中,

????????最后由于B拿到了A的对象引用,所以B现在也能获取到A对象,并完成了初始化。

最后说一下并不是所有单例Spring都能解决以来循环。

可以解决的单例:①都是setter注入,②都是属性注入,③一个B是setter注入,一个A是构造器注入(A中注入B(setter),B中注入A(构造器))

不能解决的单例:①都是构造器注入,②一个A是setter注入,一个B是构造器注入(B中注入A,A中注入B)

原因是 Spring 在创建 Bean 时默认会根据自然排序进行创建,A 会先于 B 进行创建。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章           查看所有文章
加:2022-09-30 00:38:26  更:2022-09-30 00:43:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/24 13:24:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码