Spring三级缓存的数据结构是什么

ps:如果这篇帖子对于还在找工作和找实习的你有所帮助,可以关注我,给本贴点赞、评论、收藏并订阅专栏;同时不要吝啬您的花花

一、核心前置说明

Spring的三级缓存定义在 DefaultSingletonBeanRegistry 类中,是解决单例Bean循环依赖、保证Bean创建线程安全的核心机制。三级缓存本质均为线程安全的Map集合,但键值类型、存储对象、使用场景完全不同,底层依托 ConcurrentHashMap 实现高并发读写,兼顾线程安全与性能。

三级缓存的Key统一为Bean名称(String类型),仅Value类型存在差异,这是Spring缓存查找、替换、销毁的核心依据。

二、三级缓存逐层级数据结构拆解

1. 一级缓存:singletonObjects(成品单例池)

数据结构private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256)

泛型定义:Key = String(Bean的唯一名称),Value = Object(完整初始化的单例Bean实例

核心特性

  • 存储已完成实例化、属性填充、初始化(init-method/PostProcessor)的成熟Bean,是Spring对外提供Bean的最终数据源
  • 一旦Bean存入一级缓存,后续所有获取Bean的操作都会直接命中该缓存,无需重复创建
  • 容量初始值256,采用ConcurrentHashMap保证多线程下的安全读写,无锁化设计提升并发性能

2. 二级缓存:earlySingletonObjects(早期半成品缓存)

数据结构private final Map<String, Object> earlySingletonObjects = new HashMap<>(16)

泛型定义:Key = String(Bean的唯一名称),Value = Object(仅完成实例化、未完成属性填充的早期Bean实例

核心特性

  • 存储无AOP增强的早期Bean,仅用于循环依赖场景下的临时暴露
  • 底层为HashMap(非线程安全),因为Spring通过singletonObjects锁(一级缓存锁)控制并发,无需额外线程安全保障
  • 当Bean完全初始化后,二级缓存中的数据会被移除,最终数据沉淀到一级缓存

3. 三级缓存:singletonFactories(工厂缓存)

数据结构private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16)

泛型定义:Key = String(Bean的唯一名称),Value = ObjectFactory<?>(Bean工厂函数式接口,用于生成Bean实例)

核心特性

  • 三级缓存是解决AOP循环依赖的关键,Value并非Bean实例,而是延迟创建Bean的工厂对象
  • ObjectFactory是函数式接口,仅含 getObject() 方法,调用时才会生成Bean(含AOP代理对象)
  • Bean实例化后立即存入三级缓存,属性填充阶段若触发循环依赖,会通过工厂生成早期Bean,并存入二级缓存
  • 同样采用HashMap,由singletonObjects锁保证并发安全,初始化完成后清空当前Bean的三级缓存数据

三、三级缓存数据结构对比总结

一级缓存

singletonObjects

ConcurrentHashMap

完整Bean实例

对外提供最终单例Bean

二级缓存

earlySingletonObjects

HashMap

早期半成品Bean(无AOP)

普通循环依赖临时存储

三级缓存

singletonFactories

HashMap

ObjectFactory<?>工厂对象

解决AOP代理循环依赖

四、关键设计细节补充

  • 三级缓存的查找优先级:一级缓存 > 二级缓存 > 三级缓存,逐级查找保证Bean获取效率
  • singletonObjects采用ConcurrentHashMap,是因为一级缓存是全局共享的最终数据源,必须支持高并发安全访问
  • 二、三级缓存用HashMap,是因为Spring通过singletonObject锁(同一时间仅一个线程创建Bean)规避并发问题,兼顾性能与内存开销
  • 三级缓存的工厂模式,实现了Bean实例化与AOP代理的解耦,避免循环依赖时提前创建代理导致的逻辑异常
  • 无循环依赖场景下,Bean实例化后仍会放入三级缓存:这是Spring的固定创建流程,并非只有循环依赖才会触发三级缓存存放。Bean完成实例化后,会无条件加入三级缓存;若无循环依赖,整个属性填充、初始化阶段不会调用三级缓存的ObjectFactory工厂,也就不会生成早期Bean、不会用到二级缓存;待Bean完全初始化并迁入一级缓存后,Spring会主动清理当前Bean对应的三级缓存数据,避免内存冗余。

ps:如果这篇帖子对于还在找工作和找实习的你有所帮助,可以关注我,给本贴点赞、评论、收藏并订阅专栏;同时不要吝啬您的花花

Spring 文章被收录于专栏

本专栏聚焦Spring全生态体系,从IoC/AOP核心原理入手,覆盖Spring Boot自动配置、事务管理、Web开发等实战内容。拆解循环依赖、动态代理等高频面试难点,助力开发者从入门到精通,打通单体到微服务的技术链路,解决企业级开发痛点,提升架构设计与问题排查能力,成为Java后端进阶的必备技术专栏。

全部评论

相关推荐

评论
点赞
1
分享

创作者周榜

更多
正在热议
更多
# 春招至今,你的战绩如何? #
10404次浏览 92人参与
# 你的实习产出是真实的还是包装的? #
1848次浏览 42人参与
# MiniMax求职进展汇总 #
23984次浏览 308人参与
# 军工所铁饭碗 vs 互联网高薪资,你会选谁 #
7554次浏览 43人参与
# 简历第一个项目做什么 #
31654次浏览 334人参与
# 重来一次,我还会选择这个专业吗 #
433430次浏览 3926人参与
# 米连集团26产品管培生项目 #
5919次浏览 215人参与
# 当下环境,你会继续卷互联网,还是看其他行业机会 #
187091次浏览 1122人参与
# 牛客AI文生图 #
21422次浏览 238人参与
# 不考虑薪资和职业,你最想做什么工作呢? #
152343次浏览 888人参与
# 研究所笔面经互助 #
118893次浏览 577人参与
# 简历中的项目经历要怎么写? #
310201次浏览 4208人参与
# AI时代,哪些岗位最容易被淘汰 #
63614次浏览 817人参与
# 面试紧张时你会有什么表现? #
30503次浏览 188人参与
# 你今年的平均薪资是多少? #
213067次浏览 1039人参与
# 你怎么看待AI面试 #
180017次浏览 1249人参与
# 高学历就一定能找到好工作吗? #
64324次浏览 620人参与
# 你最满意的offer薪资是哪家公司? #
76480次浏览 374人参与
# 我的求职精神状态 #
448036次浏览 3129人参与
# 正在春招的你,也参与了去年秋招吗? #
363361次浏览 2638人参与
# 腾讯音乐求职进展汇总 #
160633次浏览 1111人参与
# 校招笔试 #
470822次浏览 2964人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务