https://zhuanlan.zhihu.com/p/62382615

循环依赖发生的时机

Bean 实例化主要分为三步,如图:

问题出现在:第一步和第二步的过程中,也就是填充属性 / 方法的过程中

Spring 如何解决的

  • Spring 为了解决单例的循环依赖问题,使用了 三级缓存 ,递归调用时发现 Bean 还在创建中即为循环依赖
  • 单例模式的 Bean 保存在如下的数据结构中:
/** 一级缓存:用于存放完全初始化好的 bean **/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256); /** 二级缓存:存放原始的 bean 对象(尚未填充属性),用于解决循环依赖 */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16); /** 三级级缓存:存放 bean 工厂对象,用于解决循环依赖 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16); /**
bean 的获取过程:先从一级获取,失败再从二级、三级里面获取 创建中状态:是指对象已经 new 出来了但是所有的属性均为 null 等待被 init
*/

检测循环依赖的过程如下:

  • A 创建过程中需要 B,于是 A 将自己放到三级缓里面 ,去实例化 B
  • B 实例化的时候发现需要 A,于是 B 先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了!
    • 然后把三级缓存里面的这个 A 放到二级缓存里面,并删除三级缓存里面的 A
    • B 顺利初始化完毕,将自己放到一级缓存里面(此时B里面的A依然是创建中状态)
  • 然后回来接着创建 A,此时 B 已经创建结束,直接从一级缓存里面拿到 B ,然后完成创建,并将自己放到一级缓存里面
  • 如此一来便解决了循环依赖的问题

一文说透 Spring 循环依赖问题的更多相关文章

  1. spring循环依赖问题分析

    新搞了一个单点登录的项目,用的cas,要把源码的cas-webapp改造成适合我们业务场景的项目,于是新加了一些spring的配置文件. 但是在项目启动时报错了,错误日志如下: 一月 , :: 下午 ...

  2. Spring 循环依赖

    循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映为一个环.此处不 ...

  3. Springboot源码分析之Spring循环依赖揭秘

    摘要: 若你是一个有经验的程序员,那你在开发中必然碰到过这种现象:事务不生效.或许刚说到这,有的小伙伴就会大惊失色了.Spring不是解决了循环依赖问题吗,它是怎么又会发生循环依赖的呢?,接下来就让我 ...

  4. Spring 循环依赖的三种方式(三级缓存解决Set循环依赖问题)

    本篇文章解决以下问题: [1] . Spring循环依赖指的是什么? [2] . Spring能解决哪种情况的循环依赖?不能解决哪种情况? [3] . Spring能解决的循环依赖原理(三级缓存) 一 ...

  5. Spring循环依赖的解决

    ## Spring循环依赖的解决 ### 什么是循环依赖 循环依赖,是依赖关系形成了一个圆环.比如:A对象有一个属性B,那么这时候我们称之为A依赖B,如果这时候B对象里面有一个属性A.那么这时候A和B ...

  6. 这个 Spring 循环依赖的坑,90% 以上的人都不知道

    1. 前言 这两天工作遇到了一个挺有意思的Spring循环依赖的问题,但是这个和以往遇到的循环依赖问题都不太一样,隐藏的相当隐蔽,网络上也很少看到有其他人遇到类似的问题.这里权且称他非典型Spring ...

  7. Spring — 循环依赖

    读完这篇文章你将会收获到 Spring 循环依赖可以分为哪两种 Spring 如何解决 setter 循环依赖 Spring 为何是三级缓存 , 二级不行 ? Spring 为啥不能解决构造器循环依赖 ...

  8. 帮助你更好的理解Spring循环依赖

    网上关于Spring循环依赖的博客太多了,有很多都分析的很深入,写的很用心,甚至还画了时序图.流程图帮助读者理解,我看了后,感觉自己是懂了,但是闭上眼睛,总觉得还没有完全理解,总觉得还有一两个坎过不去 ...

  9. spring 循环依赖的一次 理解

    前言: 在看spring 循环依赖的问题中,知道原理,网上一堆的资料有讲原理. 但今天在看代码过程中,又产生了疑问. 疑问点如下: // 疑问点: 先进行 dependon 判断String[] de ...

随机推荐

  1. JavaScript 词法句法

    JavaScript 中的几个重要概念 JavaScript 遵循 ECMA-262 规范,目前其最新版是 ECMAScript 2018,而获得所有主流浏览器完全支持的则是 ECMAScript 5 ...

  2. 火狐中添加selenium IDE

    在火狐中添加selenium IDE 1.下载selenium IDE,此处下载的是selenium-ide-2.5.0.xpi 2.在火狐中,打开菜单-->附加组件-->用户附加组件的工 ...

  3. fuseki远程访问方法

    ./fuseki-server启动服务后,我们的服务只能是localhost访问,无法被其他人访问,那么 要怎么修改呢.很简单,把apche-jena-fuseki-3.10.0/run 下面的shi ...

  4. vs2010编译C++ 栈的使用

    // CTest.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #include &l ...

  5. Windows上设置Sass

    现在有很多信息在预处理器上浮动.大部分信息都面向Mac用户,所以在这篇文章中,我提供了一个非常简单的指南,帮助基于Windows的开发人员快速启动并运行Sass(我选择的预处理器). 本文是在此博客上 ...

  6. JDK8~JDK11的新特性

    #JDK 1.8 新特性接口中的静态方法 只能由接口自己调用 接口中的默认方法 可以不被覆盖 #JDK 1.9 新特性(可能在JDK8中被忽略了,没来得及加)接口可以定义私有方法,但是只能让自己调用, ...

  7. 文献阅读报告 - Social BiGAT + Cycle GAN

    原文文献 Social BiGAT : Kosaraju V, Sadeghian A, Martín-Martín R, et al. Social-BiGAT: Multimodal Trajec ...

  8. eshop1-大型电商架构演进

    1. 项目初期 2. 服务器分离 以上的服务分离架构,即使文件服务crash 了,但是application server 和 Database Server 继续可以访问运行 3. 基于并发访问越来 ...

  9. Java中null的判断

    Java中空指针的异常十分常见 if (name != null && !name.equals("")) { //do something } 或者 if (!& ...

  10. PHP: isset与empty的区别

    PHP的isset()函数 一般用来检测变量是否设置 功能:检测变量是否设置 返回值: 若变量不存在则返回 FALSE 若变量存在且其值为NULL,也返回 FALSE 若变量存在且值不为NULL,则返 ...