spring 三级缓存map存储了工厂对象。工厂对象具体指的是什么呢?

1 个回答

  • 刘峰
    杯中之物从来不能消愁补过
    ### **1. `singletonFactories`(三级缓存)存的到底是什么?** 在 Spring 三级缓存机制中: - **一级缓存(`singletonObjects`)**:存储**完全初始化的单例 Bean**。 - **二级缓存(`earlySingletonObjects`)**:存储**早期暴露但尚未完全初始化的 Bean 实例**。 - **三级缓存(`singletonFactories`)**:存储的是 **"单例 Bean 创建工厂"**,即 `ObjectFactory<?>` 对象。 🔹**关键点**: 三级缓存 `singletonFactories` 里存的是 **"Bean 的工厂对象"**,这个工厂对象(`ObjectFactory<?>`)的作用是 **当发生循环依赖时,可以提供 Bean 的“早期引用”**。 ### **2. `singletonFactories` 具体存的是什么?** 它存的并不是直接的 Bean 实例,而是**一个延迟创建 Bean 的工厂对象**,即 `ObjectFactory<?>`。 看一个 **实际存储的示例**: ```java singletonFactories.put(beanName, () -> getEarlyBeanReference(beanName, beanInstance)); ``` - 这里 `() -> getEarlyBeanReference(beanName, beanInstance)` 是一个 **Lambda 表达式**,它是 `ObjectFactory<?>` 的具体实现。 - 这个 Lambda 只有在需要时(如循环依赖发生时)才会调用 `getObject()` 方法,返回 `beanInstance`。 📌 **简单来说,`singletonFactories` 里存的是一个“函数”或者“工厂”,这个工厂可以返回 Bean 实例,但只有在真正需要的时候才执行。** ### **3. 为什么不直接存 Bean,而是存 `ObjectFactory<?>`?** 假设 `singletonFactories` 直接存的是 Bean 实例,而不是 `ObjectFactory<?>`,可能会导致: 1. **Bean 还未完成初始化,直接暴露实例,可能不完整** 2. **如果 Bean 需要 AOP 代理,但提前暴露的是原始对象,AOP 代理就无法生效** 3. **可能会引发线程安全问题** 所以,Spring **不直接存 Bean,而是存 `ObjectFactory<?>`**,这样在循环依赖时: - 先不创建完整的 Bean,而是存 `ObjectFactory<?>`,表示“**当需要时,我可以创建它**”。 - 只有当循环依赖发生时,才会真正执行 `getObject()`,拿到 Bean 实例。 ### **4. 代码示例:如何存入和取出 `singletonFactories`** Spring 在创建 Bean 时,会 **先存入 `singletonFactories`**: ```java singletonFactories.put(beanName, () -> getEarlyBeanReference(beanName, beanInstance)); ``` 当 `beanB` 依赖 `beanA`,但 `beanA` 还没完全初始化时,Spring 会: 1. 发现 `singletonFactories` 里有 `beanA` 的 `ObjectFactory<?>`。 2. 调用 `getObject()` 获取 `beanA` 的早期引用。 3. 提前把 `beanA` 放入二级缓存 `earlySingletonObjects`,让 `beanB` 能使用。 示例代码: ```java ObjectFactory<?> singletonFactory = singletonFactories.get(beanName); if (singletonFactory != null) { Object earlySingleton = singletonFactory.getObject(); // 获取beanA的早期引用 earlySingletonObjects.put(beanName, earlySingleton); singletonFactories.remove(beanName); // 用完后移除 } ``` ### **5. `singletonFactories` 三级缓存存储的具体示例** 用一个简单的 Java 代码模拟 `singletonFactories` 的作用: ```java import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; public class SpringCacheDemo { public static void main(String[] args) { // 三级缓存 Map<String, Supplier<Object>> singletonFactories = new HashMap<>(); Map<String, Object> earlySingletonObjects = new HashMap<>(); Map<String, Object> singletonObjects = new HashMap<>(); // 1. 创建BeanA的实例,但不完全初始化 Object beanA = new Object(); // 2. 把BeanA的工厂对象放入三级缓存 singletonFactories.put("beanA", () -> beanA); // 3. 发生循环依赖,获取BeanA的早期引用 if (singletonFactories.containsKey("beanA")) { Object earlyReference = singletonFactories.get("beanA").get(); earlySingletonObjects.put("beanA", earlyReference); singletonFactories.remove("beanA"); } // 4. BeanA 初始化完成,放入一级缓存 singletonObjects.put("beanA", beanA); // 输出缓存内容 System.out.println("一级缓存:" + singletonObjects); System.out.println("二级缓存:" + earlySingletonObjects); System.out.println("三级缓存:" + singletonFactories); } } ``` ### **6. 总结:`singletonFactories` 具体存储的内容** ✅ `singletonFactories` **存的不是 Bean,而是 `ObjectFactory<?>`,即 “延迟获取 Bean 的工厂对象”**。 ✅ `ObjectFactory<?>` **并不会立即执行,而是在需要时(如循环依赖发生时)才会调用 `getObject()` 取出 Bean 实例**。 ✅ **这样可以避免线程安全问题、保证 AOP 代理生效、并解决循环依赖问题**。 📌 结论: `singletonFactories` 存的是 **“能返回 Bean 的函数”**,这个函数在需要时执行,返回 Bean 实例,避免 Bean 还未初始化完成时被错误使用。
    发布于 2025-03-10 21:11 •IP属地 江西
    举报
    评论
    收藏