Spring 三级缓存

Spring三级缓存解析

Spring 三级缓存

Spring 中循环依赖的现象

1、构造器循环依赖

  • 构造器循环依赖指的是在 Bean 的构造函数中存在相互依赖的情况。当 Spring 容器在创建 Bean 时,会先调用构造函数来实例化对象。如果存在构造器循环依赖,就会陷入一个死循环,因为创建一个 Bean 需要先创建另一个 Bean,而创建另一个 Bean 又需要先创建第一个 Bean。Spring 无法解决这种循环依赖,会直接抛出 BeanCurrentlyInCreationException 异常。

2、field 属性注入循环依赖

  • 单例(singleton)scope 下 setter 方法的循环依赖:单例 Bean 在 Spring 容器中只会创建一个实例。对于使用 setter 方法进行属性注入的单例 Bean,Spring 可以利用三级缓存机制来解决循环依赖问题。其核心原理是将 Bean 的实例化和初始化过程分离,在实例化后将 Bean 提前曝光到缓存中,当其他 Bean 依赖该 Bean 时,可以从缓存中获取到未完全初始化的 Bean 实例进行注入。
  • 原型(prototype)scope 的循环依赖:原型 Bean 每次请求都会创建一个新的实例。由于每次创建都是新的对象,Spring 无法像处理单例 Bean 那样利用缓存来解决循环依赖问题。因此,对于原型 Bean 的循环依赖,Spring 不会进行处理,需要开发者自己解决。

Spring 真正创建 Bean 对象的核心类及过程

Spring 创建 Bean 对象的最核心方法为 AbstractAutowireCapableBeanFactory#doCreateBean,在这个方法中,会依次完成 Bean 对象实例化、属性注入、调用初始化方法进行一些初始化操作。

  1. createBeanInstance 方法

    此方法的核心任务是实例化 Bean 对象,其本质是调用对象的构造方法来创建对象实例。在 Spring 框架里,它会依据 Bean 的定义信息,选择合适的构造函数来创建对象。这可能涉及到无参构造函数、有参构造函数的选择,甚至可能使用工厂方法来创建对象。

  2. populateBean 方法

    该方法的主要作用是对 Bean 的依赖属性进行注入,常见的如使用 @Autowired 注解进行自动注入。在这个阶段,Spring 会查找 Bean 所依赖的其他 Bean,并将这些依赖的 Bean 注入到当前 Bean 中。

  3. initializeBean 方法

    此方法主要用于调用 Bean 的初始化方法,例如实现了 InitializingBean 接口的 afterPropertiesSet 方法,或者在 Bean 定义中指定的 initMethod 方法。这些方法通常用于在 Bean 的属性注入完成后,进行一些初始化操作。

Spring 解决循环依赖的前提条件

  • 不全是构造器方式的循环依赖:如果所有的循环依赖都是通过构造器注入实现的,Spring 无法打破循环依赖的死循环,因此必须至少有一部分依赖是通过 setter 方法或其他非构造器方式注入的。
  • 必须是单例:Spring 的三级缓存机制是基于单例 Bean 的特性实现的,只有单例 Bean 才能保证在整个应用程序的生命周期中只有一个实例,并且可以被缓存和复用。对于原型 Bean,每次请求都会创建新的实例,无法使用缓存来解决循环依赖问题。

三级缓存的作用

在 Spring 中,三级缓存主要用于解决单例 Bean 的循环依赖问题。循环依赖指的是两个或多个 Bean 之间相互依赖,形成一个闭环。例如,Bean A 依赖 Bean B,而 Bean B 又依赖 Bean A。Spring 使用三级缓存来巧妙地处理这种情况,确保单例 Bean 能够正确创建。

注意

  1. 三级缓存只能解决 setter 注入的循环依赖,无法解决构造器注入的循环依赖;
  2. 原型(prototype)作用域的 bean 无法解决循环依赖;
  3. 如果 Bean 有 AOP 代理,三级缓存中的 ObjectFactory 会返回代理对象;

getBean(AbstractBeanFactory#getBean(java.lang.String))源码看调用时序图:

1. getBean(A)  // AbstractBeanFactory
   -> doGetBean(A)
     -> getSingleton(A) [一级缓存没有]  // DefaultSingletonBeanRegistry
     -> createBean(A)   // AbstractAutowireCapableBeanFactory
       -> doCreateBean(A)
         -> 实例化A
         -> addSingletonFactory(A) [A加入三级缓存]  
         -> populateBean(A) [填充属性]
           -> getBean(B) [发现依赖B]
             -> doGetBean(B)
               -> getSingleton(B) [一级缓存没有]
               -> createBean(B)
                 -> doCreateBean(B)
                   -> 实例化B
                   -> addSingletonFactory(B) [B加入三级缓存]
                   -> populateBean(B) [填充属性]
                     -> getBean(A) [发现依赖A]
                       
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值