三级缓存揭秘:Spring 如何优雅地处理循环依赖问题

原文来自于:zha-ge.cn/java/113

三级缓存揭秘:Spring 如何优雅地处理循环依赖问题

你有没有遇到过那种"你中有我、我中有你"的 Bean 场面?有一次,我一不小心写了俩服务,A 里注入了 B,B 里又非要注入回 A。结果启动直接爆炸,简直比宫斗剧还乱。后来一琢磨,这年头连内存都三层缓存了,Spring 它到底靠啥能优雅地扛过循环依赖?今天咱就唠唠:Spring 三级缓存的江湖传说。


Spring 的 BeanFactory,其实就是一套好用的"仓库管理小精灵"。循环依赖一来,普通搞法直接凉凉,但 Spring 居然通过三级缓存,像搞"排兵布阵"一样把问题拆开来看:

  • 一级缓存(singletonObjects):成品区,搞定的 Bean 都放这儿。
  • 二级缓存(earlySingletonObjects):半成品区,可能还没初始化好,但需要提前透剧的货。
  • 三级缓存(singletonFactories):工厂区,万一再来一波操作,灵活应急!
三层缓存到底怎么救命?

说实话,第一次点进 Spring 源码看的时候,我全程黑人问号脸。终于在 AbstractBeanFactory 里,抓住了工资负责人的身影。尤其是下面这几行伪代码,让我脑补出现场画面:

java 复制代码
// Bean 创建大致流程,遇到循环依赖的时刻
if (!singletonObjects.contains(beanName)) {
    // 本地没成品,看看工厂区有没有货
    Object singleton = getSingletonFromFactory(beanName);
    if (singleton == null) {
        singleton = createBean(beanName);
        addSingleton(beanName, singleton);
    }
    // ......
}

咱们打断点调了又调,才发现每当 A、B 互相依赖时,Spring 就提前把工厂对象注册进三级缓存。A 注入 B 时(一脸无助),发现自己不在成品区,索性先暴露个"毛坯版"A。同时把它的 ObjectFactory 藏进三级缓存里,B 要用就"勉强先来一口试试"。这样能保证最终的 Bean 能在 Spring 容器安全出生。

  • 真正的对象方法注入在后面才补全,像拼图一样,总算把所有 Bean 填好。

踩坑瞬间

来,说几个让人吐血的循环依赖小故事:

  • 曾经一个朋友,手贱搞了个@Configuration,偏偏又自己注入自己,一脸懵逼连爆三次错。
  • 看源码时,误以为三级缓存等于三级缓存,全局搜 earlySingletonObjects,还以为这是个 Bug,原地自闭一个小时。
  • 曾用原生 Java 写了一次类似的"临时缓存",结果死循环到怀疑人生,还没 Spring 靠谱。

如果非要描述踩坑瞬间,就是各种"BeanCurrentlyInCreationException"的红色大字,佛系劝退新手。


经验启示

唠到这里,总算有点经验了,送你几个:

  1. 千万别轻易设计循环依赖,代码能隔离就别钻牛角尖。
  2. @Lazy、setter注入可以偶尔救命,但设计时还是要优雅些。
  3. 别把三级缓存当魔法,单例Bean有限制,不支持构造器依赖、@Scope("prototype")直接爆炸。
  4. 对自己温柔点,踩坑是成长的必经之路。毕竟三层缓存,也不是天生就会用的嘛!

最后,"收个尾巴":你要跟循环依赖过不去,Spring就跟你和解;你跟它和解,它也教会你点底层的智慧。行了,先写到这,你有没有被三级缓存救过命?欢迎留言唠嗑!

相关推荐
WooaiJava18 分钟前
AI 智能助手项目面试技术要点总结(前端部分)
javascript·大模型·html5
Never_Satisfied38 分钟前
在JavaScript / HTML中,关于querySelectorAll方法
开发语言·javascript·html
董世昌4138 分钟前
深度解析ES6 Set与Map:相同点、核心差异及实战选型
前端·javascript·es6
80530单词突击赢1 小时前
JavaWeb进阶:SpringBoot核心与Bean管理
java·spring boot·后端
爬山算法1 小时前
Hibernate(87)如何在安全测试中使用Hibernate?
java·后端·hibernate
WeiXiao_Hyy1 小时前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端
苏渡苇1 小时前
优雅应对异常,从“try-catch堆砌”到“设计驱动”
java·后端·设计模式·学习方法·责任链模式
long3162 小时前
Aho-Corasick 模式搜索算法
java·数据结构·spring boot·后端·算法·排序算法
Serene_Dream2 小时前
JVM 并发 GC - 三色标记
jvm·面试
xjt_09012 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js