您好,欢迎来到客趣旅游网。
搜索
您的当前位置:首页Spring 的三级缓存机制

Spring 的三级缓存机制

来源:客趣旅游网

Spring 在处理 循环依赖 时使用了 三级缓存机制,这是 Singleton Bean 创建过程中为了解决循环依赖的一种策略。通过三级缓存,Spring 可以提前暴露未完全初始化的对象,避免循环依赖导致的无限递归错误。


1. 三级缓存的结构

Spring IOC 容器的 三级缓存分为以下三个部分:


2. 三级缓存的工作流程

当遇到循环依赖时,Spring 会按照以下步骤来创建和管理 bean:

  1. 检查一级缓存:

    • singletonObjects 中查找,如果找到,说明这个 bean 已完全初始化,直接返回。
  2. 检查二级缓存:

    • 如果一级缓存中没有,则从 earlySingletonObjects(二级缓存)中查找。
    • 如果找到,说明这个 bean 还没完全初始化,但可以提供引用,直接返回。
  3. 检查三级缓存:

    • 如果一级和二级缓存都没有,从 singletonFactories(三级缓存)中获取一个对象工厂,调用工厂方法创建早期引用,并放入二级缓存。
  4. 放入一级缓存:

    • 完成 bean 的初始化后,将最终的对象存入 singletonObjects(一级缓存),并从二级、三级缓存中移除。

3. 示例:如何解决循环依赖

假设存在以下两个类:AB,它们互相依赖。

class A {
    private B b;

    public A(B b) {
        this.b = b;
    }
}

class B {
    private A a;

    public void setA(A a) {
        this.a = a;
    }
}

Spring 容器中创建这两个对象时,会出现循环依赖:

  1. Spring 尝试实例化 A,但 A 的构造器依赖 B
  2. 容器开始创建 B,但 BsetA() 方法又依赖 A
  3. 为了解决这个循环依赖问题,Spring 将未完全初始化的 A 的引用提前暴露到二级缓存中。
  4. 在创建 B 时,B 可以通过二级缓存获取 A 的引用,完成注入。
  5. 最终,AB 都完成初始化,并分别存入一级缓存。

4. 代码中的核心逻辑

Spring 的核心实现位于 DefaultSingletonBeanRegistry 类中。

  • 三级缓存的使用逻辑大致如下:
// 从一级缓存中获取 bean
Object singletonObject = singletonObjects.get(beanName);
if (singletonObject == null) {
    // 如果一级缓存没有,则尝试从二级缓存获取
    singletonObject = earlySingletonObjects.get(beanName);
    if (singletonObject == null) {
        // 如果二级缓存也没有,则从三级缓存的 ObjectFactory 中获取
        ObjectFactory<?> singletonFactory = singletonFactories.get(beanName);
        if (singletonFactory != null) {
            singletonObject = singletonFactory.getObject();
            // 提前暴露到二级缓存中
            earlySingletonObjects.put(beanName, singletonObject);
            singletonFactories.remove(beanName);
        }
    }
}
return singletonObject;

5. 为什么需要三级缓存?

  • 三级缓存的作用: 提前暴露一个未完全初始化的对象(或其代理)引用,避免循环依赖导致的死锁问题。
  • 为什么不直接使用二级缓存?
    • 二级缓存只能存储已经创建出的对象引用,但某些代理对象需要延迟创建。三级缓存通过 对象工厂(ObjectFactory) 延迟创建这些代理,灵活性更高。

6. 适用场景与

  1. 适用于 Setter 注入:

    • Spring 通过三级缓存可以处理 Setter 注入 场景中的循环依赖。
  2. 不适用于构造注入:

    • 如果两个 bean 通过构造器相互依赖,Spring 无法通过三级缓存解决,因为构造器必须一次性注入所有依赖。

7. 总结

  • 一级缓存: 存储完全初始化的对象。
  • 二级缓存: 存储早期暴露的对象引用,用于解决循环依赖。
  • 三级缓存: 存储对象工厂,用于延迟创建代理对象,并转移到二级缓存中。

三级缓存机制帮助 Spring 处理 Setter 注入 引发的循环依赖问题,但对于 构造器注入 的循环依赖为力。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- kqyc.cn 版权所有 赣ICP备2024042808号-2

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务