ITPub博客

首页 > 数据库 > 数据库开发技术 > Spring为什么使用三级缓存而不是两级?

Spring为什么使用三级缓存而不是两级?

原创 数据库开发技术 作者:Finally_m 时间:2024-08-06 10:09:00 0 删除 编辑

今天来聊一聊关于 Spring 为什么使用三级缓存的问题,先说结果哈,Spring框架中的三级缓存主要用于解决循环依赖问题,特别是在单例Bean的创建过程中。

下面V哥会解释为什么Spring需要三级缓存,而不是仅仅使用两级的原因。

  1. 一级缓存(Singleton Objects):存储已经完全初始化好的单例Bean。当一个Bean被成功创建并注入到其他Bean中后,它会被放入一级缓存中。

  2. 二级缓存(Early Singleton Objects):存储已经完成了BeanNameAware、BeanFactoryAware等Aware接口的回调,但是还没有完全初始化的Bean。这个缓存主要用于存放早期引用的Bean,这些Bean在完成属性填充和初始化方法调用之前,就可以被其他Bean引用。

  3. 三级缓存(Singleton Factories):存储Bean工厂对象(BeanFactory)创建Bean实例的工厂信息。这个缓存是为了解决构造器循环依赖问题。当Spring容器创建一个Bean时,如果这个Bean的构造器依赖于其他Bean,Spring会首先尝试创建这个Bean的实例,这个实例的引用会被放入三级缓存中。然后,Spring会尝试创建依赖的Bean,如果依赖的Bean也存在循环依赖,Spring会从三级缓存中获取Bean的早期引用,而不是再次创建一个新的实例。

为什么需要三级缓存:

  • 解决循环依赖:在Spring中,如果两个或多个Bean相互依赖对方的构造器,就会发生循环依赖。两级缓存无法解决这个问题,因为它们都是在Bean实例化之后才被使用。三级缓存允许在Bean实例化过程中就提供对其他Bean的引用,从而打破循环依赖。

  • 优化性能:通过使用三级缓存,Spring可以在Bean实例化阶段就解决循环依赖问题,避免了额外的Bean创建尝试,从而提高了性能。

  • 保持Bean的创建过程的原子性:三级缓存确保了Bean的创建过程是原子性的,即在Bean完全初始化之前,不会将其暴露给其他Bean。

  • 支持延迟初始化:三级缓存允许Spring在Bean完全初始化之前,就能够提供Bean的引用,这支持了延迟初始化的模式,即只有在Bean被实际使用时才进行初始化。

总而言之,言而总之,强调一下这句话:三级缓存是Spring框架解决循环依赖问题的关键机制,它允许在Bean的创建过程中提供对其他Bean的引用,同时保持了Bean创建的原子性和性能。

三级缓存使用案例

下面V 哥来一个简单的使用案例,展示如何通过Spring的三级缓存机制解决循环依赖,方便兄弟们更好的理解。

首先,定义两个Bean,它们在构造器中相互依赖:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class ClassA {
    private ClassB classB;

    @Autowired
    public ClassA(ClassB classB) {
        this.classB = classB;
    }

    // ClassA的其他方法...
}

@Component
public class ClassB {
    private ClassA classA;

    @Autowired
    public ClassB(ClassA classA) {
        this.classA = classA;
    }

    // ClassB的其他方法...
}

在这个例子中,ClassA和ClassB通过构造器相互注入,形成了循环依赖。如果没有Spring的三级缓存机制,这种情况会导致异常,因为Spring无法完成其中一个Bean的创建。

Spring框架内部是如何处理这个问题的呢?下面来介绍一下Spring容器创建这两个Bean时的大致步骤,深入理解一下:

  1. Spring容器开始创建ClassA的Bean实例,并将其放入三级缓存singletonFactories中。
  2. 容器尝试注入ClassB到ClassA的构造器中。由于ClassB还没有完全创建,Spring会尝试创建ClassB。
  3. 在创建ClassB时,容器发现ClassB的构造器需要一个ClassA的实例。由于ClassA已经在三级缓存中,Spring会使用这个早期引用来注入ClassB。
  4. 一旦ClassB被创建,它会被放入二级缓存earlySingletonObjects中,并完成剩余的初始化步骤。
  5. 然后,容器继续完成ClassA的创建和初始化,将其放入一级缓存singletonObjects中。

这样的话,即使存在循环依赖,Spring也能够通过三级缓存机制确保每个Bean都能被正确创建和注入,原来如此。

兄弟们可以移步 Spring 源码,结合这个示例再深入学习,实际的Spring实现会更复杂一些。其实,咱们在使用Spring的的时候,通常不需要直接操作这些缓存,因为Spring容器会自动处理这些逻辑。到这,你应该知道Spring如何解决循环依赖的问题了,完事,下课。

V哥原创技术文章发布于 CSDN技术社区,欢迎关注【威哥爱编程】

- END -

近期课程上新:
Java基础 | Javaweb基础 | Java高级框架 | 微服务架构 | TiDB分布式数据库入门最佳实践 | VUE全面剖析及前后端联动实战 | 23种设计模式 | 企业级项目实战 | Java面试宝典



原文作者:Java架构栈;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2021-04-13

  • 博文量
    573
  • 访问量
    243748