Spring三级缓存流程再梳理

本文主要是说下在使用spring时遇到了循环依赖,Spring利用三级缓存怎么解决

getBean(beanName)doGetBean(name, null, null, false);getSingleton(beanName)方法, 最后会通过addSingleton(beanName, singletonObject)存到一级缓存里面去createBean(beanName, mbd, args);doCreateBean(beanName, mbdToUse, args);1、实例化普通对象,生成singletonFactory对象存到三级缓存里面去,任何对象都会存到三级缓存,因为后面存一级缓存的时候,都会把三级缓存里面删掉2、填充属性,包括循环依赖3、初始化处理,AOP代理对象,如果符合AOP逻辑,那么4getSingleton(false)从缓存中获取对象,为什么上面创建对象了,这里还要再次获取对象,主要是循环依赖的时候这里可能已经生成好了。

备注:singletonFactory.getObject和Bean的初始化都会经过AOP来判断一次是否需要创建代理对象,但是二者只会有一个创建代理对象,他们里面利用了一个中间earlyProxyReferences缓存,创建过就不会再创建了,这个缓存不是三级缓存别搞混了

案例1:A和B只是普通类之间的相互引用

1、A先创建普通实例,然后生成一个singletonFactory对象存到三级缓存,没有什么条件基本上都会被塞到三级缓存里面。
2、A属性填充,发现需要B

3、调用B的CreateBean,B创建普通实例,singletonFactory对象存到三级缓存,没有什么条件,都会存到三级缓存里面去。
4、B属性填充,B里面需要A,然后通过三级缓存里面找,发现有,通过getObject得到A的实例对象引用,在存到二级缓存里面去,注意这里是A的实例对象,和前面A创建的实例对象是同一个,为什么,因为getObject虽然会触发后置处理的调用,但是因为不走AOP所以,调用完后置处理器,返回的依旧是A的普通实例,而这个A的普通实例哪里来的,就是在生成singletonFactory对象时候,把一开始生成的普通对象穿进去的。
5、因为是普通实例,所以B执行后置处理器,不走AOP,返回的依旧是普通的实例
6、再把B从三级缓存中移除,存到一级缓存里面去。

7、再回到A,此时A调用getBean就可以返回B的实例对象,这个时候,B已经在1级缓存,A还在二级缓存里面。

8、A的属性填充完之后,调用初始化方法,走后置处理器,因为不是AOP所以初始化之后得到的A还是普通实例

9、在接着走getSingleton(false)方法,这个时候A已经被丢到了二级缓存,所以getSingleton也会拿到对象,但是这里拿到的对象和A一开始实例化的对象是一样的。

10、最后再把A塞到1级缓存,从二级缓存中移除。

案例2:A和B都会创建代理对象,2者相互引用。

首先需要知道,A和B都是先创建普通实例对象,然后在把A和B这个普通实例对象的属性填充好,在通过这个普通实例对象来生成代理对象,因为代理对象最终也是会拿到这个普通实例对象,调用目标具体方法。
并且,A和B的普通实例对象,里面的属性赋值,赋的是代理对象,不是普通实例对象。

1、先普通实例化A,然后生成一个singletonFactory对象存到三级缓存
2、属性填充,发现需要注入B

3、调用B的CreateBean,B创建普通实例,singletonFactory对象存到三级缓存

4、B属性填充,B里面需要引入A,调用getSingleton(A, true);因为A已经在三级缓存里面了,所以会触发A的singletonFactory.getObject方法

5、A这个时候就会通过SmartInstantiationAwareBeanPostProcessor后置处理器来创建A的代理对象,并且会把A从三级缓存中移除,A添加到二级缓存里面去。

6、B调用初始化方法,这个时候B会通过后置处理器来创建代理对象,具体哪个后置和选用注解有差异,比如@Aspect和@Async创建代理的后置处理器就不一样。此时B的实例已经变成了代理对象。

7、B在调用getSingleton(beanName, false);方法,返回Null因为穿了false,注意此时B还是三级缓存里面,A已经不在三级缓存里面了,A已经跑了二级缓存里面去了,并且A此时已经是一个代理对象了

8、最后返回B实例化好的代理对象,存到一级缓存里面,然后清空三级缓存。

9、回到A的属性填充逻辑,因为此时B已经实例化了,然后把A的属性赋好值。

10、开始触发A的初始化方法,通过后置处理器创建A的代理对象,当发现A已经在缓存earlyProxyReferences里面,说明已经创建过A的代理对象,所以就不在创建A的代理对象,此时初始化方法返回的还是A的普通实例对象。

11、A开始调用getSingleton(A, false);因为此时二级缓存已经保存了A的代理对象,将代理对象取出替换A的普通实例对象,返回A的代理对象。

12、最后将A的代理对象存到一级缓存里面去,在移除二级缓存里面的数据。

待确认:B这个类里面的属性,填充进去的是A的普通对象还是代理对象。 代理对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/102831.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一文拿捏对象内存布局及JMM(JAVA内存模型)

1 JMM(Java Memory Model) 1 概述 Java内存模型(Java Memory Model简称JMM)是一种抽象的概念,并不真实存在,它描述的一组规则或者规范。通过这些规则、规范定义了程序中各个变量的访问方式。jvm运行的程序的实体是线程,而每个线程运行时&am…

Unity编辑器从PC平台切换到Android平台下 Addressable 加载模型出现粉红色,类似于材质丢失的问题

Unity编辑器在PC平台下使用Addressable加载打包好的Cube,运行发现能正常显示。 而在切换到Android平台下,使用Addressable时加载AB包,生成Cube对象时,Cube模型呈现粉红色,出现类似材质丢失的问题。如下图所示。 这是…

重绘与重排(回流)

前言 最近写的都是写基础知识,为了提高巩固自己的知识体系,抽空就总结或复习一个知识点。为了防范于未然,说不定哪天就得重新找工作了。如何提高渲染时间,优化前端性能,必有减少重绘和重排。之前在前端性能优化上叶有…

安全设备和防火墙

文章目录 微步TDP态势感知防火墙防火墙的负载均衡 微步TDP态势感知 安全设备的主要功能在黑名单,只要记住黑名单的功能在哪即可 常用的是威胁选项卡的监控功能,监控模块会把实时的告警列出来,只要列出来就能分析流量是误报还是真实的&#x…

【GO】基础速成

简单介绍一下go好处 编译语言,可以提前报错同时又有python的一些优点,自带多线程 开始学习 学习网站:学习网站 值 包含:字符串、整型、浮点型、布尔型等等 字符串可以 进行拼接。 需要注意的是布尔型在go里面不自动转化为in…

tomcat服务tomcat多实例部署

tomcat服务&&tomcat多实例部署 文章目录 tomcat服务&&tomcat多实例部署1.简介2.优缺点优点:缺点: 3.工作原理4.工作流程5.tomcat服务部署5.1.java环境安装5.2.拉取tomcat软件包5.3.解压部署5.4.启动tomcat服务5.5.访问tomcat的web页面5.…

Kafka数据同步原理详解

Kafka数据同步原理详解 Kafka是一种分布式的消息队列系统,它具有高吞吐量、可扩展性和分布式特性等优势。在Kafka中,数据按照主题进行分区,每个主题都有一组分区。每个分区都有自己的生产者和消费者,生产者负责向分区中写入消息&…

基于VUE的图书借阅管理系统的设计与实现

目录 一、摘要 二、技术描述 三、部分截图 四、获取方式 一、摘要 随着我国经济的高速发展,人们对图书的需求也愈发旺盛,而传统图书管理模式存在以下弊端:信息存储和分类操作不够高效,导致查找书籍困难;借还书流程…

【数据结构-栈 二】【单调栈】每日温度、接雨水

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【单调栈的应用】,使用【栈】这个基本的数据结构来实现,这个高频题的站点是:CodeTop,筛选条件为&am…

恢复grub在硬盘对多系统的引导

grub2引导被覆盖怎么办 问题的提出问题的解决1 进入try ubuntu系统2 执行如下命令 验证 问题的提出 windows和ubuntu双系统引导出错,硬盘的grub引导被windows的引导覆盖,导致只能进入windows系统,不能引导ubuntu系统。 问题的解决 1 进入t…

location rewrite

Nginx location 匹配的规则和优先级 Nginx常用的变量 rewrite: 重定向功能 Location 匹配 URI URI:统一资源的表示符,是一种字符串标识,用于标识抽象或者物理资源 先来巩固一些与location结合使用的正则表达式 正则表达式:匹…

基于安卓android微信小程序音乐播放器

运行环境 小程序前端框架:uniapp 小程序运行软件:微信开发者 后端技术:javaSsm(SpringSpringMVCMyBatis)vue.js 后端开发环境:idea/eclipse 数据库:mysql 项目介绍 音乐播放器小程序的设计主要是对系统所要实现的功能进行详细考虑,确定所要…

【机器学习 | 回归问题】超越直线:释放多项式回归的潜力 —— 详解线性回归与非线性 (含详细案例、源码)

🤵‍♂️ 个人主页: AI_magician 📡主页地址: 作者简介:CSDN内容合伙人,全栈领域优质创作者。 👨‍💻景愿:旨在于能和更多的热爱计算机的伙伴一起成长!!&…

【数据结构-字符串 四】【字符串识别】字符串转为整数、比较版本号

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【字符串转换】,使用【字符串】这个基本的数据结构来实现,这个高频题的站点是:CodeTop,筛选条件为&…

封装 Token

什么是token? 作为计算机术语,是“令牌”的意思 。 Token 是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请…

docker使用nginx

使用docker run命令运行Nginx应用 使用命令可以直接启动 [rootlocalhost ~]# docker run -d nginx:latest Unable to find image nginx:latest locally latest: Pulling from library/nginx a2abf6c4d29d: Pull complete 下载完成 a9edb18cadd1: Pull complete 589b7251471a:…

Java Day1

day01 一、Markdown 基础语法1.标题2. 字体3. 引用 >4. 分隔线 --- ***5. 图片 ![]()6.超链接7.列表8.表格9.代码 代码名称 二、计算机三、常用快捷键1. Win 系列2. Ctrl 系列3. ALt 系列 四、 基本的DOS命令1. 打开方式:2. 常用DOS命令 五、计算机语言发展史第一…

【软件测试学习】—软件测试知识点总结(二)

【软件测试学习】—软件测试的分类(二) 一、软件测试的分类 二、软件的生命周期 三、软件测试的工作流程 四、软件测试用例设计方法 (一)、等价类划分 定义:等价类划分是一种典型的、重要的黑盒测试的方法&#xff…

从零开始探索C语言(十一)----共用体和位域

文章目录 1. 共用体1.1 定义共用体1.2 访问共用体成员 2. 位域2.1 位域声明2.2 位域的定义和位域变量的说明2.3 位域的使用2.4 位域小结 1. 共用体 共用体是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型。您可以定义一个带有多成员的共用体&#…

JavaFx学习问题2--音频、视频播放失败情况

文章目录 一、路径注意事项:① 用相对路径的时候别忘了前面的斜杠② uri问题 二、播放不了的问题① 获取的媒体文件路径本身就是不对的② 必须是uri 额外收获: 一、路径注意事项: ① 用相对路径的时候别忘了前面的斜杠 并不是什么大问题,只是…