Spring如何使用三级缓存解决循环依赖
Spring如何使用三级缓存解决循环依赖
首先来了解一下什么是循环依赖
@Component
public class A {
@Autowired
B b;
}
@Component
public class B {
@Autowired
A a;
}
在对象A创建过程中,需要注入B,因为容器中没有B,则去创建B,B创建过程中又需要注入A,而A在等待B的创建,B在等待A的创建,导致两者都无法创建成功,无法加入到单例池供用户使用。
Spring则通过三级缓存来解决循环依赖的问题,另外如果对象的作用范围是Prototype,则无法通过三级缓存解决循环依赖,会抛出BeanCurrentlyInCreationException异常,构造注入的方式,也无法解决循环依赖,只有set注入可以解决。
那么三级缓存又是什么呢?
三级缓存就是三个Map
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
//一级缓存(单例池,经过完成生命周期的对象会放入其中)
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//二级缓存(刚实例化还未初始化的原始对象会放入其中)
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
//三级缓存(存放创建某个对象的工厂)
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
Spring Bean对象从创建到初始化大致会经过四个流程
getSingleton()、doCreateBean()、populateBean()、addSingleton()
getSingleton:从单例池中获取bean对象,如果没有,则进行创建doCreateBean():创建bean对象populateBean():填充依赖,如果被填充的对象不存在于单例池,则进行创建等四个流程addSingleton():将初始化完成的对象加入到单例池
循环依赖的对象在三级缓存中的迁移过程
A 创建过程中需要 B, 于是 A 将自己放到三级缓存里面,去实例化 B
B 实例化的时候发现需要 A,于是 B 先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存
找到了A,然后把三级缓存中的 A 放到二级缓存,并删除三级缓存中的 A
B 顺利初始化完毕,将自己放到一级缓存中(此时 B 中的 A 还是创建中状态,并没有完全初始化),删除三级缓存中的 B
然后接着回来创建 A,此时 B 已经完成创建,直接从一级缓存中拿到 B,完成 A 的创建,并将 A 添加到单例池,删除二级缓存中的 A
图示:

Spring如何使用三级缓存解决循环依赖的更多相关文章
- Spring三级缓存解决循环依赖
前提知识 1.解决循环依赖的核心依据:实例化和初始化步骤是分开执行的 2.实现方式:三级缓存 3.lambda表达式的延迟执行特性 spring源码执行逻辑 核心方法refresh(), popula ...
- Spring ioc(4)---如何解决循环依赖
前面说到对象的创建,那么在创建的过程中Spring是怎么又是如何解决循环依赖的呢.前面提到有个三级缓存.就是利用这个来解决循环依赖.打个比方说实例化A的时候,先将A创建(早期对象)放入一个池子中.这个 ...
- spring: 我是如何解决循环依赖的?
1.由同事抛的一个问题开始 最近项目组的一个同事遇到了一个问题,问我的意见,一下子引起的我的兴趣,因为这个问题我也是第一次遇到.平时自认为对spring循环依赖问题还是比较了解的,直到遇到这个和后面的 ...
- 曹工说Spring Boot源码(29)-- Spring 解决循环依赖为什么使用三级缓存,而不是二级缓存
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- Spring 动态代理时是如何解决循环依赖的?为什么要使用三级缓存?
前言 在研究 『 Spring 是如何解决循环依赖的 』 的时候,了解到 Spring 是借助三级缓存来解决循环依赖的. 同样在上一节留下了疑问: 循环依赖为什么要使用三级缓存?而不是使用二级缓存? ...
- Spring如何解决循环依赖问题
目录 1. 什么是循环依赖? 2. 怎么检测是否存在循环依赖 3. Spring怎么解决循环依赖 本文主要是分析Spring bean的循环依赖,以及Spring的解决方式. 通过这种解决方式,我们可 ...
- Spring解决循环依赖,你真的懂了吗?
导读 前几天发表的文章SpringBoot多数据源动态切换和SpringBoot整合多数据源的巨坑中,提到了一个坑就是动态数据源添加@Primary接口就会造成循环依赖异常,如下图: 这个就是典型的构 ...
- Spring如何解决循环依赖,你真的懂了?
导读 前几天发表的文章SpringBoot多数据源动态切换和SpringBoot整合多数据源的巨坑中,提到了一个坑就是动态数据源添加@Primary接口就会造成循环依赖异常,如下图: 这个就是典型的构 ...
- Spring是如何解决循环依赖的
前言 在面试的时候这两年有一个非常高频的关于spring的问题,那就是spring是如何解决循环依赖的.这个问题听着就是轻描淡写的一句话,其实考察的内容还是非常多的,主要还是考察的应聘者有没有研究过s ...
随机推荐
- android签名分析及漏洞修复
本篇我们来看看android的签名机制.发布出来的apk都是有META-INF文件夹,里面包含如下三个文件: 下面来一一解释这三个文件的作用(打包apk时签名过程):SignApk.main() 1. ...
- phpstorm 实现分屏显示
- Jmeter软件安装之Mac
Jmeter软件安装之Mac 一.环境准备 安装JDK 下载Jmeter 二.下载Jmeter 下载地址: http://jmeter.apache.org/download_jmeter.cgi,下 ...
- 2021ArchSummit全球架构师峰会上,大家在聊些什么
大会PPT公开下载链接:https://ppt.infoq.cn/list/assh2021 大会主要情况介绍 2021 ArchSummit全球架构师峰会是该大会正式成立的第十年,是极客邦科技旗下I ...
- SSM久别遇新坑
SSM久别遇新坑 久别个锤子,也就几天没看,改bug改到怀疑人生 maven的父子模块问题 众所周知,用maven建立一个空的模块,在它之下,将原本的各层次结构分别新建为一个子模块,就能够将各业务进行 ...
- 手写一个最简单的IOC容器,从而了解spring的核心原理
从事开发工作多年,spring源码没有特意去看过.但是相关技术原理倒是背了不少,毕竟面试的那关还是得过啊! 正所谓面试造火箭,工作拧螺丝.下面实现一个最简单的ioc容器,供大家参考. 1.最终结果 2 ...
- utf8字符集下的比较规则
前言: 在MySQL中,比较常用的字符集是utf8和utf8mb4.这两个字符集是类似的,utf8是utf8mb3的别名,所以之后在MySQL中提到utf8就意味着使用1~3个字节来表示一个字符,如果 ...
- 发现数据结构与算法之美的第n次重新学习 ——— 初遇数据结构与算法(了解)
你的数据结构怎么学的?提起数据结构,计算机与软件,it行业内无人不知,无人不晓.但是,当你真正的去通过数据结构与算法内容去实践内容时,真的能联系起来吗?那肯定的 不管是考研还是做项目,数据结构都是必学 ...
- jQuery清空元素和克隆元素
1.清空 $(function () { $('#btn').click(function () { $('#ul1').html('') $('#ul1').empty() $('#ul1').re ...
- 登录框-element-ui 样式调节
element-ui样式调节 首先设置布局 如果想要实现如下效果 需要两行,然后设置偏移,第一行中间只是站位,没有内容,可以考虑使用div占位,设置最小高度 el-card调整圆角 border-ra ...