Spring 一 :三级缓存问题

65 阅读3分钟

Spring为什么需要三级缓存

Spring的三级缓存用来解决循环依赖问题,那二级缓存能解决的事情为什么要三级缓存来解决呢?当Spring创建一个bean的时候,它不仅仅是实例化对象,还会进行属性赋值、调用初始化方法等一系列步骤,以确保这个bean完全准备好。但在循环依赖的情况下,这一系列的初始化步骤可能会被中断。这就是为什么我们有"早期bean引用"(early bean reference)。这是一个已经被实例化但尚未完全初始化(例如属性还未赋值)的bean。当我们说"从二级缓存中直接取bean",我们指的是直接获取这个“早期的bean引用”。但是,这个引用是“裸”的,它只是一个实例化的对象,并没有完全完成初始化。 简而言之,它可能还不是一个可以立即使用的bean,因为它还缺少一些重要的初始化步骤。而三级缓存(SingletonFactories)中的工厂对象,它的主要目的是当请求一个bean的时候,不仅返回这个“早期的bean引用”,还可以对其进行后续的初始化操作。比方说,想象你正在组装一辆车。这辆车的引擎已经装好了,但车门还没装。如果你直接从“仓库”(这里可以想象为二级缓存)中拿这辆车,你得到的是一辆没有车门的车。但是,如果你有一个“工厂”(这里可以想象为三级缓存中的工厂对象),这个工厂在给你这辆车的同时,还会帮你装上车门,这样你得到的就是一辆完整的车。 这就是二级缓存和三级缓存之间的关键区别。

三级缓存与AOP

第三级缓存(SingletonFactories)与Spring的AOP(面向切面编程)确实有关系。为了理解这个关系,我们需要先了解Spring AOP是如何工作的。

在Spring中,AOP的一个常见用例是代理。当你为一个bean应用一个切面(如事务管理或日志记录),Spring会为该bean创建一个代理对象。这个代理对象会“包裹”原始的bean,并在适当的时候调用切面逻辑。

现在,考虑以下情况:

  1. Bean A依赖于Bean B。
  2. Bean B有一个与其相关的切面,因此它需要被代理。
  3. 在创建Bean A的过程中,我们需要注入Bean B。但此时,Bean B尚未完全初始化,并且其代理尚未创建。

这时,三级缓存(SingletonFactories)就发挥作用了。它存储了一个能够生成Bean B代理对象的工厂。当Bean A请求Bean B的引用时,这个工厂不仅返回Bean B的引用,还确保Bean B被正确地代理。

简而言之,三级缓存确保在处理循环依赖的时候,即使涉及AOP代理,也可以正确地返回bean引用。