Spring为什么要用三级缓存解决循环依赖?

Spring为什么要用三级缓存解决循环依赖?

    • [1. Spring是如何创建一个bean对象](#1. Spring是如何创建一个bean对象)
    • [2. Spring三级缓存](#2. Spring三级缓存)
      • [2.1 一级缓存:单例池,经历过完整bean生命,单例Bean对象](#2.1 一级缓存:单例池,经历过完整bean生命,单例Bean对象)
      • [2.2 二级缓存:提前暴露的Bean](#2.2 二级缓存:提前暴露的Bean)
      • [2.3 三级缓存:打破循环](#2.3 三级缓存:打破循环)
    • [3. Spring 解决不了的循环依赖](#3. Spring 解决不了的循环依赖)
    • 4.总结

1. Spring是如何创建一个bean对象

  1. 类

  2. 推断构造方法

    默认采用无参构造,如果不存在无参构造,判断有参构造受否唯一,如果唯一选择有参构造,不唯一报错。

  3. 普通对象

  4. 依赖注入

  5. 初始化前(@PostConstruct)

    在类中方法上添加@PostConstruct注解,该方法会在初始化前执行。

  6. 初始化(InitializingBean)

    类实现InitializingBean接口,重写afterPropertiesSet方法。

  7. 初始化后(AOP)

  8. 代理对象

  9. 放入Map单例池

  10. Bean对象

2. Spring三级缓存

通过分析源码:

doCreateBean方法

2.1 一级缓存:单例池,经历过完整bean生命,单例Bean对象

复制代码
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

2.2 二级缓存:提前暴露的Bean

复制代码
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

2.3 三级缓存:打破循环

复制代码
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

//<beanName, 单例创建的工厂>

在创建bean 的源码中先判断是否是单例,支持循环依赖,当前正在创建的单例, 满足上面条件就会创建一个lambda表达式放入三级缓存中。

getEarlyBeanReference方法中会判断是否存在AOP,存在就创建代理对象,不存在就返回通过构造方法创建的普通对象。

在三级缓存lambda方法中判断是否创建代理对象

上边源码中看到只要走三级缓存的会调用getEarlyBeanReference方法,该方法会把执行过AOP的Bean存放在earlyProxyReferences的Map集合中,用于后续bean生命周期的初始化后是否AOP创建代理对象校验。

初始化后,校验是否AOP创建代理对象,通过校验earlyProxyReferences集合中bean是否与传入bean相同来判断。

获取单例bean

3. Spring 解决不了的循环依赖

1.构造器循环依赖(实例化阶段循环依赖) 解决办法添加@Lazy注解

底层原理是创建代理对象,

4.总结

在Java Spring的厨房里,循环依赖这道菜可是让不少程序员大厨头疼的"黑暗料理"。但Spring大厨微微一笑,不慌不忙地亮出了他的秘密武器------三级缓存"时光机"!

一级缓存,那是"秒出"区,新鲜出炉的Bean直接上桌,快得就像外卖小哥的闪电送。

二级缓存,咱们叫它"半成品天堂",Bean们在这里稍作休息,等待最后的调味。但别急,好戏还在后头!

重头戏来了,三级缓存------"未来豆预测局"!这里,Spring大厨仿佛拥有了预知未来的超能力,提前把即将诞生的Bean们"画"在纸上,等它们真正诞生时,直接对号入座,无缝衔接。这操作,简直比科幻电影还炫酷!

就这样,Spring大厨用三级缓存的"时光机",轻松玩转循环依赖这道难题,让厨房里的Bean们手拉手也能和谐共处,共同烹饪出美味的应用大餐。程序员们纷纷点赞:"Spring大厨,你是我们的超级英雄!"

相关推荐
做科研的周师兄3 分钟前
【R语言实战】MixSIAR 氢氧同位素水源解析全流程:从混合空间校验到贝叶斯 MCMC 收敛诊断(后附完整代码)
java·大数据·开发语言
有点小困97713 分钟前
Spring Boot 异步任务 ClassLoader 踩坑实录:ClassNotFoundException 的诡异真相
java
aiks_yuan16 分钟前
Java 正则表达式很慢怎么办:Pattern 预编译只快 2~5 倍,真正卡死线程的是回溯(JDK 8、11、17 实测)
java
用户37215742613518 分钟前
C# 填写 PDF 交互式表单:文本框、复选框、单选按钮和下拉列表
java
IT枫斗者枫哥21 分钟前
Java 退款请求超时,先查原单还是重试?
java·后端
特立独行的猫A25 分钟前
我用仓颉写了个多平台发文工具:一份 Markdown,一条命令发六个平台
java·后端·python
ikgy38 分钟前
JAVA EE:1.计算机是如何工作的
java·java-ee
AI技术新视界1 小时前
LLM 提示词缓存(Prompt Caching)的秘密
人工智能·缓存·llm·prompt
.痞老板.1 小时前
java ee--计算机是如何工作的
java·开发语言·java-ee
青梅味猪大肠2 小时前
【操作系统-60】临近适应算法
java·linux·开发语言·嵌入式硬件·算法·操作系统