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 ...
随机推荐
- Google Hacking的用法
目录 Google Hacking 基本搜索 高级搜索 Index of inurl Google Hacking Google Hacking 是利用谷歌搜索的强大,来在浩瀚的互联网中搜索到我们需要 ...
- UVA11520填充正方形
题意: 给你一个n*n的矩阵,让你往里面添加大写字母,矩阵有的字母已经给填好了,然后要求是每个格子都不能与他相邻的格子的大写字母相同,如果有多个答案,输出从上到下,从左到右所连接的成的那个n ...
- 解决在Vim中鼠标右键不能粘贴问题
最近维护一台服务器,使用putty登录后,用vim时,鼠标右键不能 粘贴而是进入了visual模式.网上查找一番找到了解决方法: 方 法一:在普通模式下键入" :set mouse-=a&q ...
- 脱壳入门----常见的寻找OEP的方法
一步直达法 所谓的一步直达法就是利用壳的特征.壳一般在执行完壳代码之后需要跳转到OEP处,而这个跳转指令一般是call ,jmp ,push retn类型的指令,而且因为壳代码所在的区段和OEP代码所 ...
- c#操作可道云api帮助类
代码: public class KodCloudHelper { static readonly string kodCloudUrl = Configs.GetString("KodCl ...
- 关于有符号数和无符号数的转换 - C/C++
转载自:http://www.94cto.com/index/Article/content/id/59973.html 1.引例: 今天在做了一道关于有符号数和无符号数相互转换及其左移/右移的问题, ...
- 在Visual Studio 中使用git——浏览版本库(七)
在Visual Studio 中使用git--什么是Git(一) 在Visual Studio 中使用git--给Visual Studio安装 git插件(二) 在Visual Studio 中使用 ...
- 登陆框select绕过
0x00 原理 思路来自美团杯2021,本来说出题人已经把select通过正则过滤了,就不该总是往用select进行查询那方面想-> select id from users where u ...
- [云计算] OpenStack 发展史
传统数据中心面临的问题 无法管理,资源利用率不高 资源分配不合理 初始成本高 发展阶段 IDC 托管/租用 VPS(虚拟专用主机/OpenVZ/XEN) 虚拟主机 云主机 虚拟化 服务器虚拟化 KVM ...
- 分布式存储ceph---ceph概念及原理(1)
一.Ceph简介: Ceph是一种为优秀的性能.可靠性和可扩展性而设计的统一的.分布式文件系统.ceph 的统一体现在可以提供文件系统.块存储和对象存储,分布式体现在可以动态扩展.在国内一些公司的云环 ...