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个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
内容推荐
Day 68时间19:00~ 22:00(3h)✅ 今天做了:Component注解、Mybatis配置、使用⏰ 明天计划:Lombok、Mapper映射、动态SQL📚 今日感悟:自动配置类DataSourceAutoConfiguration ,会读取properties文件,通过注解:@EnableConfigurationProperties(DataSourceProperties.cl
2
Day 19✅ 今天做了:MCP⏰ 明天计划:AI智能体构建📚 今日感悟:今天MCP问题有点多有点杂,明天找时间再捋一下。继续加油
1
Day 25✅ 今天做了:1、扇贝英语单词打卡2、英语听说读写、听力练习3、微信阅读15分钟4、编程导航学习⏰ 明天计划:待定📚 今日感悟:Keep going!
2
Day 104✅ 今天做了:学习了Java反射及快速入门⏰ 明天计划:继续学习Java反射
1
为啥codex老是提示这个啊
0
作者分享
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
