技术博客
Spring框架中的循环依赖解析:三级缓存的机制与作用

Spring框架中的循环依赖解析:三级缓存的机制与作用

作者: 万维易源
2026-06-17
循环依赖三级缓存Spring框架HashMap注册表
> ### 摘要 > 本文解析Spring框架中循环依赖的解决机制,重点阐述其核心注册表所采用的三级缓存结构。该机制依托三个独立的HashMap实例实现,每一级缓存承担明确职责:一级缓存存放完全初始化完成的Bean;二级缓存保存早期暴露的、尚未完成属性注入的Bean引用;三级缓存则存储ObjectFactory,用于按需创建代理对象。三级设计在功能上严格分离,避免职责重叠,从而在保障线程安全与对象一致性的同时,高效化解循环依赖问题。 > ### 关键词 > 循环依赖,三级缓存,Spring框架,HashMap,注册表 ## 一、循环依赖问题概述 ### 1.1 循环依赖的定义与表现形式,探讨在Spring框架中常见的依赖场景 循环依赖,是指两个或多个Bean在初始化过程中相互持有对方的引用,形成闭环依赖关系。在Spring框架中,这种现象并非罕见——例如,ServiceA依赖ServiceB,而ServiceB又在构造器或setter方法中直接注入ServiceA;又或在基于注解的配置下,`@Autowired`字段引发的隐式引用链悄然闭合。这类依赖虽在逻辑建模中偶有合理性,却在容器启动阶段暴露出尖锐的时序矛盾:若严格遵循“先完全创建、再注入依赖”的线性流程,任一Bean都将因等待对方就绪而陷入无限等待。正因如此,循环依赖成为Spring生命周期管理中最富张力的典型问题之一,它不单是代码结构的映射,更是对象协作边界与初始化契约之间的一次无声博弈。 ### 1.2 循环依赖对应用程序的影响,包括性能问题和潜在的异常情况 当循环依赖未被妥善处理时,Spring容器在刷新上下文阶段将抛出`BeanCurrentlyInCreationException`,明确标识某Bean正处于创建中却已被提前请求——这不仅是启动失败的信号,更预示着应用逻辑根基的松动。即便在部分宽松配置下绕过校验,未经协调的早期引用也可能导致Bean状态不一致:如代理未织入、事务切面缺失、或AOP增强逻辑失效,进而引发运行时行为偏差。此外,过度依赖循环结构会削弱模块解耦性,使单元测试难以隔离,调试路径复杂化,长期来看,它悄然抬高了系统的维护成本与演进风险。 ### 1.3 Spring框架解决循环依赖的基本思路与传统方法的局限性 Spring选择了一条务实而精巧的路径:不禁止循环依赖,而是通过“提前暴露正在创建中的Bean引用”来打破僵局。其核心在于放弃“全量初始化完成后再发布”的教条,转而允许在实例化后、属性填充前,将原始对象(非代理)暂存并对外提供。然而,若仅依赖单级缓存存放半成品对象,则无法兼容代理场景——因为代理需在初始化后生成,而此时原始对象已被提前暴露,后续代理替换将导致引用不一致。若采用二级缓存(如仅存原始对象与代理对象),又难以兼顾“按需创建”与“线程安全”的双重约束。传统方案在此陷入两难:简化则失灵活,强化则增耦合。 ### 1.4 为什么需要三级缓存:解决复杂场景下循环依赖的必要性 正是在这种张力之下,三级缓存应运而生——它不是冗余堆叠,而是职责精密咬合的工程结晶。这三级缓存均以HashMap的形式存储数据,共同构成Spring框架核心注册表的有机部分。一级缓存专注终态,确保已完全初始化的Bean可被稳定复用;二级缓存承接过渡,保存早期暴露的、尚未完成属性注入的Bean引用,为依赖方提供即时可用的“骨架”;而三级缓存则独担智能调度之责,仅存储ObjectFactory,延迟代理对象的创建时机,直至真正需要时才执行工厂逻辑。三者功能上严格分离,彼此间无职责重叠,既保障了线程安全,又维系了对象一致性。这种分层设计,让Spring在面对含AOP、事务、循环引用等多重交织的复杂场景时,依然能从容拆解依赖闭环——它不靠妥协,而以结构的清晰,回应混沌的挑战。 ## 二、三级缓存架构解析 ### 2.1 Spring框架中Bean生命周期与依赖注入的基本原理 在Spring的世界里,Bean的诞生并非一蹴而就的线性旅程,而是一场精密编排的仪式:从类加载、实例化(`new`对象),到属性填充(依赖注入)、初始化方法执行(如`@PostConstruct`),再到最终就绪供应用调用——每一步都承载着容器对“可控性”与“可预测性”的执着。依赖注入,正是这场仪式中最富人情味的一环:它不强制Bean自证其能,而是由容器悄然牵线,将彼此需要的对象温柔交付。然而,当ServiceA凝望ServiceB的同时,ServiceB也正回望着ServiceA,这份双向奔赴便成了生命周期流程中的一个温柔悖论。Spring并未以“禁止”来划下冰冷界限,而是选择在实例化完成的刹那,为尚未走完全部流程的Bean预留一道门缝——既不破坏初始化契约,也不辜负协作期待。这扇门,正是三级缓存得以安放的哲学支点:它承认不完美时刻的存在,并为之设计尊严。 ### 2.2 注册表在Spring框架中的角色与结构组成 注册表,是Spring容器沉默却坚定的心脏。它不参与业务逻辑的喧哗,却默默记录着每一个Bean从初生到成熟的全部轨迹;它不执行方法调用,却支撑着整个依赖网络的寻址与调度。作为Spring框架核心注册表的组成部分,三级缓存均以HashMap的形式存储数据——这一看似朴素的选择,实则是工程理性与运行效率的双重妥协:HashMap提供O(1)的查找性能,契合高频读写场景;其线程不安全性则由Spring在关键路径上辅以同步机制予以兜底。三个HashMap并非并列堆砌,而是依职责纵深排布,共同构成一张有层次、有边界、有呼吸感的内存图谱。它们共享“注册表”之名,却各自守持一方语义疆域:一个存放终局答案,一个暂存过渡身影,一个仅保管生成答案的密钥。这种结构上的克制与清晰,让注册表超越了单纯的数据容器,升华为一种关于“何时暴露、如何暴露、为何如此暴露”的架构宣言。 ### 2.3 三级缓存的整体架构:一级缓存、二级缓存和三级缓存的定位与关系 三级缓存不是数字游戏,而是职责的郑重分封。一级缓存居于高位,如一座已完成雕琢的圣殿,只收纳完全初始化完成的Bean——它代表确定性,是外部世界唯一可信赖的引用源;二级缓存则立于廊庑之间,收容那些已实例化、尚未填充属性的早期Bean引用,它是危机中的临时驿站,为循环链条中的另一端提供可触达的“形”;而三级缓存静处最深处,不存对象,只存ObjectFactory——这个轻盈却极富张力的函数式接口,是代理逻辑的伏笔,是AOP织入的引信,是按需创建的庄严承诺。三者之间无交集、无覆盖、无冗余:一级不向下兼容未完成态,二级不越界代行代理职责,三级不提前具象化任何实例。它们以HashMap为基座,以职责为界碑,在Spring的核心注册表中构筑起一道既柔韧又坚固的缓冲带——不是为了掩盖复杂,而是为了让复杂,各安其位。 ### 2.4 三级缓存如何协同工作:从创建到注入的完整流程解析 当Spring启动一个Bean的创建之旅,三级缓存便悄然启动协奏:首先,Bean被实例化,此时容器立即将其ObjectFactory注册至三级缓存——这并非交付成品,而是埋下一粒可随时萌发的种子;若此时有其他Bean发起依赖请求,容器便从三级缓存中取出该工厂,即时创建原始对象并暂存于二级缓存,再将其注入请求方——整个过程如一次无声的接力,原始对象尚未经历属性填充与初始化,却已能支撑起依赖闭环;待该Bean自身完成属性注入与初始化后,容器将其从二级缓存移出,升级入驻一级缓存,同时清空对应三级缓存条目——至此,一个Bean完成身份跃迁,从“可被借用的过渡态”,成长为“可被信赖的终态”。三级缓存由此形成闭环:三级负责“可创建”,二级负责“已暴露”,一级负责“已就绪”。它们不争高下,只问本分;不抢功绩,只守时序——正是这份克制的协作,让Spring在万千并发与千般切面交织的现实洪流中,始终稳握对象一致性的舵盘。 ## 三、三级缓存的职责划分 ### 3.1 一级缓存:存储完全初始化的Bean实例,确保单例的唯一性 一级缓存是Spring容器中最具分量的一道门楣——它不接纳试探,不收容未竟,只向世界庄严交付一个答案:这个Bean,已走完全部生命周期,经受过属性注入、初始化回调、Aware接口调用、后处理器增强等全部洗礼,此刻完整、稳定、可复用。它以HashMap的形式存储数据,键为Bean名称(或类型标识),值为最终就绪的单例实例。在这里,单例不再是一个抽象概念,而是一种被严格兑现的契约:同一容器内,无论多少次`getBean()`调用,返回的始终是同一个对象引用。这种确定性,是应用逻辑得以扎根的土壤;这种唯一性,是事务边界、线程上下文、AOP代理生效的前提。当开发者写下`@Service`并期待一次注入即永恒时,一级缓存正默默伫立于幕后,以最朴素的哈希寻址,守护着最不容妥协的工程信条——完成,才配被看见。 ### 3.2 二级缓存:存储半成品Bean实例,解决循环依赖中的中间状态 二级缓存是一处温柔的妥协,也是一次精准的让渡。它不承诺完整,却敢于在混沌初开之际伸出援手:当Bean刚被`new`出来、尚未填充属性、也未执行任何初始化方法时,它便被悄然放入二级缓存——不是作为成品陈列,而是作为“可被借用的形体”暂存。这一设计,直指循环依赖中最脆弱的时间断点:ServiceA正在等待ServiceB注入,而ServiceB恰在此刻需要ServiceA的引用。若无二级缓存,二者将彼此凝望至容器崩溃;而有了它,ServiceA便可从二级缓存中取出那个尚带余温的原始对象,完成自己的属性装配,从而让闭环得以松动、流程得以延续。它以HashMap的形式存储数据,键名如旧,值却是尚未成熟的Bean引用——轻如薄雾,却重若支点。这不是对规范的背离,而是对协作本质的深刻体认:有时,一个“能用的影子”,比一个“完美的缺席”更接近系统真实的呼吸节奏。 ### 3.3 三级缓存:存储Bean工厂对象,处理代理对象的创建问题 三级缓存是最沉默的智者,也是最克制的匠人。它不保存对象,甚至不保存对象的雏形;它只保管一把钥匙——`ObjectFactory`,一个延迟执行的函数式接口,封装着“何时创建、如何创建、是否需代理”的全部逻辑。当某个Bean被标记为需AOP增强或事务管理时,其代理不能在实例化后立即生成(否则将与后续属性注入冲突),也不能等到初始化完毕再统一织入(否则早期暴露的引用将指向原始对象而非代理)。三级缓存正是为此而生:它让代理的诞生,严格锚定在“第一次真正被请求”那一刻。它以HashMap的形式存储数据,键为Bean名称,值仅为工厂本身——轻盈、惰性、不可变。这并非技术上的退让,而是一种面向未来的预留:它把创建权交还给时机,把一致性托付给契约,让Spring在面对CGLIB代理、JDK动态代理、泛型擦除等重重复杂性时,依然保有从容转身的余地。 ### 3.4 各缓存层级的数据结构与实现细节:HashMap的应用 三级缓存均以HashMap的形式存储数据——这一选择看似寻常,实则承载着Spring对性能、可维护性与语义清晰性的三重审慎。HashMap提供平均O(1)时间复杂度的存取能力,完美匹配注册表高频读写、低延迟响应的核心诉求;其开放的内部结构亦便于Spring在关键路径上施加细粒度同步(如`ConcurrentHashMap`的分段锁或`Collections.synchronizedMap`的包装),在保障线程安全的同时,避免全局锁带来的性能瓶颈。更重要的是,HashMap的语义纯粹:它不隐含排序、不强制序列化、不引入额外行为,仅忠实地履行“键值映射”这一单一职责——这与三级缓存各自严守边界的架构哲学高度同频。三个HashMap,三种状态,三重责任,共同织就Spring框架核心注册表的内存基座:不喧哗,自有声;不繁复,自有力。 ## 四、缓存的读写机制 ### 4.1 一级缓存的读取与写入机制:确保Bean实例的唯一性 一级缓存是Spring容器中最具仪式感的存在——它不接纳试探,不收容未竟,只向世界庄严交付一个答案:这个Bean,已走完全部生命周期。它的读取,是应用层每一次`getBean()`调用最笃定的归宿;它的写入,则是一场严格守序的加冕:唯有当Bean完成属性注入、初始化回调、Aware接口调用及所有后处理器增强之后,容器才将其以键值对形式,郑重存入那个以HashMap为基座的终局殿堂。这里没有临时工位,没有过渡席位,只有经过完整淬炼后的单例实例。也正是凭借这一不可绕行的准入门槛,一级缓存以最朴素的数据结构,兑现了Spring最核心的契约:同一容器内,同一名字的Bean,永远指向同一个对象引用。这不是技术上的权宜之计,而是一种近乎信仰的坚持——完成,才配被看见;确定,才值得托付。 ### 4.2 二级缓存的访问时机:在循环依赖中的关键作用 二级缓存从不主动现身,却总在最危急的刹那悄然托住下坠的逻辑链条。它的访问,永远发生在“第一次被其他Bean请求”之时——不是在容器启动之初,也不是在配置扫描阶段,而是在ServiceA正伸手向ServiceB索要引用、而ServiceB又恰好需要回望ServiceA的那个毫秒级断点。此时,一级缓存尚空,三级缓存只握着一把未启封的钥匙,唯有二级缓存,捧出那个刚被`new`出来、尚未填充属性、也未执行任何初始化方法的原始对象。它不承诺功能完备,却足以支撑起一次合法的字段注入;它不担保行为一致,却能让依赖闭环在不失控的前提下松动、延展、继续呼吸。这种精准到毫秒的介入,不是对流程的干扰,而是对协作本质的深切体察:系统真正的韧性,往往不在完美无瑕的终态里,而在那些被温柔接住的、尚未完成的瞬间。 ### 4.3 三级缓存的特殊处理:代理对象的延迟创建 三级缓存是整套机制中最富哲思的一环——它不存储对象,甚至不存储对象的影子,只安静存放一个`ObjectFactory`,像一封未拆封的信,承载着“何时创建、如何创建、是否需代理”的全部伏笔。它的特殊性,正在于这份极致的克制:当一个Bean被标记为需AOP增强或事务管理时,代理不能在实例化后立即生成(否则将与后续属性注入冲突),也不能等到初始化完毕再统一织入(否则早期暴露的引用将指向原始对象而非代理)。于是,三级缓存选择等待——等第一次真正被请求的那一刻,才让工厂执行、让代理诞生、让切面落位。它以HashMap的形式存储数据,键为Bean名称,值仅为工厂本身,轻盈、惰性、不可变。这不是技术上的退让,而是一种面向未来的预留:把创建权交还给时机,把一致性托付给契约。 ### 4.4 缓存之间的数据流转与一致性保证机制 三级缓存之间的流转,是一场无声而严密的交接仪式:Bean实例化后,其`ObjectFactory`首先进驻三级缓存;若此时被提前请求,则工厂被触发,原始对象生成并转入二级缓存,供依赖方即时使用;待该Bean完成全部初始化流程后,它便从二级缓存中被取出,正式入驻一级缓存,同时对应条目自三级缓存中彻底清除。整个过程如钟表齿轮般咬合:三级不越界生成实例,二级不擅自升级状态,一级不向下兼容未完成态。三者均以HashMap的形式存储数据,结构统一却语义分明;它们共享注册表之名,却各自守持一方疆域。这种流转不靠魔法,而靠职责的绝对清晰与边界的不可逾越——正是这份克制的秩序,让Spring在面对循环依赖、AOP代理、多线程并发等多重现实压力时,依然能稳稳托住对象一致性这枚最珍贵的砝码。 ## 五、循环依赖的解决流程 ### 5.1 简单循环依赖场景:两个Bean互相依赖的解决过程 当ServiceA与ServiceB彼此凝望,一个在构造器中索要对方,一个在setter里静候回音——这看似微小的双向引用,却在Spring容器启动的刹那掀起一场无声风暴。此时,一级缓存空空如也,二级缓存尚未落座,而三级缓存已悄然将ServiceA的`ObjectFactory`登记入册。当ServiceB的创建流程行至依赖注入阶段,它向容器索要ServiceA;容器未在一级缓存中寻得终态实例,便转向三级缓存,取出那个被郑重托付的工厂,即时生成ServiceA的原始对象,并将其稳稳置入二级缓存——这一动作不带修饰,不加代理,仅以最本真的形态,为闭环撕开一道可通行的缝隙。ServiceB由此完成属性填充,继续前行;待其自身初始化完毕,再轮到ServiceA补全剩余流程:属性注入、初始化回调、后处理器增强……最终,它从二级缓存中被托起,升入一级缓存,成为系统中不可撼动的单例。三级缓存均以HashMap的形式存储数据,职责如刻,流转如契——不是用妥协消解矛盾,而是以结构的清醒,在两个名字之间,架起一座可信赖的桥。 ### 5.2 复杂循环依赖:多Bean循环依赖的处理策略 当依赖链延伸为A→B→C→A,或更幽微的网状交织,循环不再只是两点之间的对视,而成为一场多线程下协同演进的精密共舞。Spring并未为“多”增设新缓存,亦未重写注册表逻辑——它依然仰赖那三个以HashMap的形式存储数据的核心缓存,仅凭职责的绝对清晰与调用时序的严格守序,便足以拆解混沌。关键在于:每个Bean的创建都独立触发三级缓存注册,每次依赖请求都遵循“一级→二级→三级”的降序探查路径;而任一Bean一旦进入二级缓存,即成为其他环节可信赖的临时支点。这种机制不因节点增多而膨胀,不因路径嵌套而失序——因为三级缓存的设计初衷,本就不是应对“数量”,而是锚定“状态”:谁完成了?谁暴露了?谁待创建?三者边界如刀裁,互不侵越。于是,在A等待B、B等待C、C又回溯至A的闭环里,容器依序为三者分别注册工厂、按需暴露原始对象、最终统一升级至一级缓存——没有魔法,只有结构的韧性;没有特例,只有规则的普适。 ### 5.3 循环依赖与AOP的交互:代理对象的创建时机 代理,是Spring赋予Bean的第二重生命,却也是循环依赖中最易失衡的变量。若在ServiceA刚被实例化时便急切织入事务切面,那么当ServiceB从二级缓存中取走它时,拿到的将是代理对象;而ServiceA后续的属性注入,却发生在原始对象上——两处引用指向不同实体,一致性轰然崩塌。正因如此,三级缓存的存在,不是锦上添花,而是生死攸关的隔离墙。它只存储`ObjectFactory`,将代理的诞生,牢牢锁死在“第一次真正被请求”的瞬间:ServiceB首次获取ServiceA时,工厂被触发,返回原始对象并暂存于二级缓存;而当ServiceA自身完成初始化、即将被外部调用时,容器才再次通过三级缓存中的工厂,生成并返回代理对象——此时,一级缓存接收的已是最终形态。三级缓存均以HashMap的形式存储数据,但它的价值,不在存储本身,而在为代理逻辑预留出不可压缩的时间间隙。这份延迟,不是性能的让步,而是对“对象身份唯一性”最庄重的捍卫。 ### 5.4 构造器注入与属性注入在循环依赖处理中的差异 构造器注入,是Spring中最为刚性的依赖表达——它要求所有参数在实例化那一刻即全部就位。正因如此,当ServiceA通过构造器依赖ServiceB,而ServiceB又反向依赖ServiceA时,三级缓存机制将无力介入:因为构造器执行前,ServiceA甚至尚未拥有自己的`ObjectFactory`,更无法注册至三级缓存;容器无“钥匙”可取,自然无法生成原始对象供ServiceB使用。此时,`BeanCurrentlyInCreationException`将必然抛出,循环依赖被明确拒绝。相较之下,属性注入(含`@Autowired`字段或setter方法)则天然兼容三级缓存——实例化可在无依赖状态下先行完成,随后才触发依赖查找与注入,为三级缓存的介入留出完整时间窗口。这种差异并非设计缺陷,而是Spring以机制语言作出的价值声明:构造器注入守护的是对象的不可变性与完整性,而属性注入则为协作弹性保留余地。三级缓存均以HashMap的形式存储数据,但它们所能调度的,从来只是“可暴露的状态”,而非“不可协商的契约”。 ## 六、性能考量与优化 ### 6.1 三级缓存的性能优势:减少重复创建与内存占用 三级缓存不是冗余的堆砌,而是对“何时创建、创建什么、为谁创建”这一连串问题的精密应答。它以三个独立的HashMap实例为基座,将对象生命周期的不同切片——终态、过渡态、可创建态——严格锚定在各自专属的存储空间中。正因职责无重叠,才杜绝了同一Bean在多个缓存中反复注册、多次实例化、多处引用不一致的浪费。当ServiceA被请求时,若其ObjectFactory已驻留三级缓存,容器便无需重新解析配置、无需再次调用构造器、更无需重复执行类加载——仅需一次工厂调用,即可按需生成原始对象;而该对象一旦进入二级缓存,便成为后续所有同名依赖的统一供给源,彻底规避了并发场景下多个线程各自创建ServiceA副本的风险。这种“一次准备、按需交付、全局复用”的机制,使三级缓存成为Spring框架中沉默却高效的节流阀——它不靠压缩数据,而靠厘清责任;不靠牺牲语义,而靠尊重时序,在保障功能完备的同时,悄然削减着重复创建的开销与无谓的内存驻留。 ### 6.2 缓存一致性:避免并发环境下的数据竞争 在高并发的容器刷新阶段,多个线程可能同时触发对同一Bean的依赖请求——此时,若缺乏明确的状态边界与写入约束,极易陷入“读写撕裂”:一个线程刚将原始对象放入二级缓存,另一个线程却已从一级缓存中取走旧版本代理,或第三个线程正试图向三级缓存重复注册同一工厂。三级缓存的设计,正是以结构本身构筑一致性防线:一级缓存只接纳完全初始化完成的Bean,二级缓存仅收容已实例化但未填充属性的对象,三级缓存则严守“只存ObjectFactory、绝不存实例”的铁律。三者均以HashMap的形式存储数据,但它们的写入时机被严格锁定在生命周期的特定节点——三级缓存写入发生于实例化之后、属性注入之前;二级缓存写入仅发生在首次被其他Bean请求时;一级缓存写入则必须等待全部初始化逻辑执行完毕。这种由职责驱动的时序锁,配合Spring在关键路径上施加的同步机制,使三个HashMap虽各自独立,却共同织就一张逻辑自洽、状态可控的内存契约网——不是靠锁住一切来换取安全,而是让每个缓存,都只做它唯一该做的事。 ### 6.3 内存管理:三级缓存对系统资源的影响 三级缓存以三个HashMap的形式存储数据,结构轻量、语义清晰,却在内存使用上展现出惊人的克制与理性。它不预分配、不缓存冗余、不保留过期引用:一级缓存中的对象是单例终态,长期驻留但数量可控;二级缓存中的对象仅为循环依赖破局所设,一旦对应Bean完成初始化,即刻被移出并升入一级缓存,生命周期短暂而精准;三级缓存最为精悍——它不持有任何Bean实例,仅保存轻量的ObjectFactory函数式接口,内存 footprint 几乎恒定。这种分层托管策略,使Spring在应对复杂依赖图谱时,既避免了单级缓存因过度暂存半成品而导致的内存淤积,也规避了多级冗余缓存引发的引用泄漏风险。三个HashMap,三种存在方式,共同构成一种低侵入、可预测、易回收的内存治理范式——它们不争抢空间,只恪守边界;不堆砌容量,只响应需要。 ### 6.4 性能优化建议:针对不同场景的缓存配置策略 三级缓存作为Spring框架核心注册表的组成部分,其设计本身已高度内聚且不可替代,因此并不支持外部干预式“配置”——它不是可开关的特性,而是容器启动流程中自动启用的底层机制。所有优化,皆源于对这一机制本质的理解与顺应:若应用大量采用构造器注入,应主动识别并重构循环依赖链,因三级缓存无法介入构造阶段;若存在高频AOP增强场景,则需确保Bean定义明确标注`@Scope("singleton")`,以保障三级缓存中ObjectFactory的稳定注册与复用;对于非单例Bean(如`prototype`),三级缓存天然不生效,此时应避免对其施加循环依赖期待。所有这些策略,都不改变三级缓存本身的结构——它们均以HashMap的形式存储数据,职责划分早已固化于Spring源码之中。真正的优化,从来不在修改缓存,而在理解缓存为何如此存在,并让代码,谦卑地生长在其逻辑疆域之内。 ## 七、总结 三级缓存是Spring框架解决循环依赖问题的核心机制,作为其核心注册表的组成部分,三者均以HashMap的形式存储数据,结构统一而职责分明。一级缓存确保完全初始化Bean的终态可用与单例唯一性;二级缓存承接早期暴露的半成品引用,为循环链条提供关键支点;三级缓存则专注延迟代理创建,仅存储ObjectFactory,实现按需生成与状态隔离。三者功能上严格分离,避免重叠,共同保障线程安全与对象一致性。该设计不回避复杂性,而是通过清晰的分层与精准的时序控制,在构造器注入受限、AOP交织、多Bean闭环等现实场景中,稳健化解依赖僵局——它不是权宜之计,而是Spring对“可控性”与“可预测性”的体系化践行。