Spring的三级缓存
斗胆写一篇技术博客,记录今天学习的三级缓存解决循环依赖问题,写的错误的和不好的地方请大家见谅(((φ(◎ロ◎;)φ)))
三级缓存的概念
1. 第一级缓存(Singleton Objects):
- 存放已经完全初始化好的单例bean.当一个bean被完全创建并初始化后,它会被存储在这里.
2. 第二级缓存(Early Singleton Objects):
- 存放原始的bean对象,即已经实例化但还没有完全初始化的bean.当Spring容器创建一个bean并注入了所有依赖项后,但还未调用afterPropertiesSet()方法或init-method时,bean会被存放在这里.
3. 第三级缓存(Singleton Factories):
- 存放ObjectFactory,即bean创建工厂(用于创建早期对象).当Spring容器创建bean的实例时,但还未进行属性填充(依赖注入)之前,会先存放一个bean工厂在第三级缓存中.
循环依赖解决过程详解:
- Bean A 的创建初始化:
- Spring容器开始创建Bean A.
- 实例化:容器首先实例化Bean A(new OperationA()),此时它是一个原始的Java对象,不包含任何Spring的代理或增强.
- 第三级缓存:这个原始对象被包装为一个ObjectFactory,并存入第三级缓存(SingletonFactories).
- Bean A 请求 Bean B:
- 在Bean A的属性填充过程中,Spring容器发现Bean A需要依赖Bean B.
- Bean B 创建:容器开始创建Bean B,同样先实例化Bean B.
- Bean B 请求 Bean A:
- 类似于Bean A,Bean B在属性填充时需要依赖Bean A.
- 早期引用:由于Bean A尚未完全初始化,Spring容器从第三级缓存中取出Bean A的ObjectFactory.
- 第二级缓存:调用ObjectFactory得到Bean A的早期引用(一个尚未填充属性的Bean A实例),并将其存入第二级缓存(EarlySingletonObjects).
- Bean B 依赖注入 Bean A:
- 将Bean A的早期引用注入到Bean B中.
- Bean B 初始化:Bean B完成属性填充,执行afterPropertiesSet或自定义的初始化方法,然后从第二级缓存移动到第一级缓存(SingletonObjects).
- Bean B 完成创建:
- Bean B现在是一个完全初始化的单例对象,可以从第一级缓存中获取.
- Bean A 依赖注入 Bean B:
- 回到Bean A的创建过程,Spring容器从第一级缓存中获取完全初始化的Bean B.
- Bean A 完成属性填充:
- Bean A的所有属性(包括注入的Bean B)都已填充完毕.
- Bean A 初始化:
- 执行Bean A的afterPropertiesSet或自定义的初始化方法.
- Bean A 完成创建:
- Bean A从第二级缓存移动到第一级缓存,现在是一个完全初始化的单例对象.
- Bean A 和 B 都可用:
- 至此,Bean A和Bean B都完全创建并初始化,可以被应用程序使用.
- 概念区分:
- 实例化对象:指的是Java的new操作创建的对象,此时对象尚未经过Spring容器的任何处理.
- 早期对象:指的是已经实例化但还未完全初始化的bean,它存在于第二级缓存中.
- 完全初始化对象:指的是已经完成所有属性填充和初始化方法调用的bean,存在于第一级缓存中.
- 对象工厂(ObjectFactory):是一个能够创建bean实例的工厂,存在于第三级缓存中,用于在循环依赖中提前暴露bean的早期引用.
- 实例工厂(Instance Factory):通常指的是Spring容器内部用于创建bean实例的逻辑,这里可以认为是ObjectFactory的具体实现.
通过以上方式,就通过引入三级缓存,解决了循环依赖的问题,在上述流程执行完之后,ServiceA和ServiceB都被成功的完成了实例化和初始化.
欢迎大佬批评指正!
评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
内容推荐
day1 二分查找 26.9.15
2
day42今天开始做伙伴匹配系统,目前只完成了前端初始化和主页的导航栏和底部栏的编写。抢阿里云云服务器没抢到,明天定个闹钟抢。今天收到最右的笔试了,后天晚上7点。还有约了一个自研电话初试,明天下午2点。用友的全栈工程师笔试和ai面还没有做。感觉9月份笔试面试确实多一些,希望在笔试面试中成长,一次错记住不足的地方并提升。算法一题,java基础。
2
🚩JavaD151、写了三段代码,没有代码提示,只有阿里巴巴代码规范插件2、"写完"和"写好"代码差距太大3、Kimi制定了一份52周的学习计划,每天都有具体的代码计划,希望能坚持
1
今天学习了:①Python基础之——四大序列(list、tuple、dict、set)和两大流程控制(条件判断/模式匹配+for/while循环)②Python函数之——函数的定义、调用以及五大类参数设置和传递
2
day2 移除元素[双指针/栈的思维] 26.9.16
1
作者分享
HTTP和HTTPS差别之一
2
初探多模态RAG
5
好好好 三天被老登安排的明明白白 麻了
但今天还是抽空复习了Redis!为自己点赞!
1
记录一下 15:31完成场景题复习 感觉忘掉的10%不到 可喜可贺 下了大功夫终究还是会有收获的
MQ启动
1
记录一下 10:28 完成数据库复习 也就那点东西
数据库范式与反范式 更新事务是怎么实现的 bufferpool 四个隔离级别,如何解决脏读幻读不可重复读 MVCC原理
索引 联合索引 索引下推 索引覆盖 索引失效原因 索引的作用
锁 行级锁 表级锁 意向锁 字典锁用来保证表结构不被改变 auto-inc锁确保主键自增
自增主键用完了怎么办
orderby实现原理 filesort 全字段排序 row_id
数据库的主从复制 两阶段提交 组复制 binlog undolog redolog分别什么作用
InnoDB的数据结构 为什么用B+树不用跳表 redis为什么用跳表不用B+树
逻辑都蛮清晰的,真真切切感受到老前辈们的奇思妙想
技术性的八股还是比较容易记住的,常看常新。用的时候一些犄角旮旯奇奇怪怪的东西就比较难记了
加油吧!半小时后开组会 也算是完成了上午的任务 中午算法继续 下午先场景题 再mq 晚上redis
3
