Spring 三级缓存
文章目录
-
- Spring 三级缓存
-
- Spring 中循环依赖的现象
- 三级缓存的作用
- 三级缓存对象
- 三级缓存工作流程
-
- 操作三级缓存的核心源码
- 三级缓存处理循环依赖的流程
- 理解三级缓存——singletonFactories
- 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 对象实例化、属性注入、调用初始化方法进行一些初始化操作。
-
createBeanInstance
方法此方法的核心任务是实例化 Bean 对象,其本质是调用对象的构造方法来创建对象实例。在 Spring 框架里,它会依据 Bean 的定义信息,选择合适的构造函数来创建对象。这可能涉及到无参构造函数、有参构造函数的选择,甚至可能使用工厂方法来创建对象。
-
populateBean
方法该方法的主要作用是对 Bean 的依赖属性进行注入,常见的如使用
@Autowired
注解进行自动注入。在这个阶段,Spring 会查找 Bean 所依赖的其他 Bean,并将这些依赖的 Bean 注入到当前 Bean 中。 -
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 能够正确创建。
注意:
- 三级缓存只能解决 setter 注入的循环依赖,无法解决构造器注入的循环依赖;
- 原型(prototype)作用域的 bean 无法解决循环依赖;
- 如果 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]