三级缓存揭秘: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就跟你和解;你跟它和解,它也教会你点底层的智慧。行了,先写到这,你有没有被三级缓存救过命?欢迎留言唠嗑!

相关推荐
xuejianxinokok3 小时前
Postgres 18 的新功能
后端·postgresql
渣哥3 小时前
为什么几乎所有 Java 项目都离不开 IoC?Spring 控制反转的优势惊人!
javascript·后端·面试
用户3856803349963 小时前
appium从入门到精通php,移动端自动化测试Appium 从入门到项目实战Python版
后端
前端赵哈哈3 小时前
Vue I18n 完整安装与使用指南
前端·vue.js·面试
深蓝电商API3 小时前
网页结构解析入门:HTML、CSS、JS 与爬虫的关系
javascript·css·html
code_Bo3 小时前
前端使用snapdom报错问题
前端·javascript·vue.js
天天摸鱼的java工程师3 小时前
SpringCloud + Nacos + Feign + Resilience4j:微服务间调用的熔断降级与重试策略
后端
勤奋菲菲3 小时前
Egg.js 完全指南:企业级 Node.js 应用框架
开发语言·javascript·node.js
一壶浊酒..4 小时前
什么是AJAX
前端·javascript·ajax