spring三级缓存解析

发布时间:2026/7/1 7:13:46
spring三级缓存解析 为了理解三级缓存的必要性我们可以从“如果没有它会怎样”来反向推导。1. 一级缓存为什么不够Spring 创建 Bean 的流程是实例化 - 属性注入 - 初始化。问题所在如果只有一级缓存存放完整 Bean当 A 和 B 循环依赖时A 在实例化后需要注入 B但 B 还没创建完成不在缓存中。这会导致 A 无法继续陷入死锁。结论一级缓存无法解决循环依赖。2. 二级缓存为什么还不够为了解决上述问题Spring 引入了二级缓存用于存放早期暴露的、未完成属性注入的原始对象。运作机制A 实例化后先将自己原始对象放入二级缓存。这样B 在创建并需要注入 A 时就能从二级缓存中找到这个“半成品”A完成注入。A 随后也能拿到完整的 B最终完成自己的创建。新问题AOP场景如果 A 需要被 AOP 增强如Transactional那么容器中最终需要的其实是 A 的代理对象而非原始对象。如果此时 B 从二级缓存拿到的是 A 的原始对象完成注入。而 A 最终初始化时又生成了一个新的代理对象。这就导致 B 中注入的 A 和最终容器里的 A 不是同一个对象程序会出错。结论二级缓存可以解决非 AOP 场景的循环依赖但无法保证 AOP 场景下代理对象的唯一性。3. 三级缓存如何完美解决为了解决 AOP 带来的对象不一致问题Spring 引入了三级缓存存储的是ObjectFactory工厂对象。运作机制存入工厂A 实例化后不是直接把自己放入二级缓存而是将一个能“生产”自己的ObjectFactory放入三级缓存。获取对象当 B 需要注入 A 时会从三级缓存拿到 A 的ObjectFactory然后调用其getObject()方法来获取 A 的早期引用。关键一步在这个getObject()方法中Spring 会检查 A 是否需要 AOP 代理。如果需要则创建 A 的代理对象。如果不需要则直接返回 A 的原始对象。存入二级缓存这个获取到的对象代理或原始会被存入二级缓存并移除三级缓存中对应的工厂。巧妙之处保证了对象的唯一性通过二级缓存确保了 A 的代理对象一旦被创建后续所有依赖 A 的 Bean 拿到的都是同一个代理对象。实现了延迟创建三级缓存中的工厂getObject()方法只会在循环依赖发生时被调用。如果没有循环依赖这个工厂方法可能永远不会执行避免了不必要的 AOP 代理提前创建符合 Spring 的设计原则。符合设计原则一级缓存只存放完整的 Bean。如果直接把不完整的代理对象放入一级缓存会破坏其设计语义。 总结Spring 的三级缓存是一个层层递进的设计一级缓存是最终目标存放完整的单例 Bean。二级缓存是“急救站”为解决循环依赖提供早期对象并保证代理对象的单例性。三级缓存是“工厂”它的存在是为了延迟创建 AOP 代理对象仅在需要时才生成从而完美地解决了支持 AOP 情况下的循环依赖问题。