spring三级缓存解决循环依赖
作者:互联网
spring三级缓存解决循环依赖
前言
我们都知道,在spring中属性的赋值是通过自动注入完成的,那么在自动注入的过程中它又是如何解决循环依赖的呢?
提示:本篇文章属于原创,请勿抄袭。
一、循环依赖
要搞明白spring是如何解决循环依赖,首先我们要弄明白什么是循环依赖,如图所示:
有两个 service 对象,分别是 userService 和 orderService,它们各自都有一个引用对方的属性,互相循环引用着对方。
二、三级缓存
在 spring 中,解决循环依赖主要是通过三级缓存来实现的,它们分别是:
- singletonObjects (一级缓存)
- earlySingletonObjects (二级缓存)
- singletonFactories (三级缓存)
对应的源码如下:
// 一级缓存,存放的是已经实例化,并且初始化后的单例对象(也叫单例池)
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 三级缓存,存放的是 ObjectFactory,通过 ObjectFactory 的 getObject()可以拿到已经实例化,但是并未初始化的对象
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
// 二级缓存,存放的是已经实例化,但是并未初始化的对象
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
三、spring解决循环依赖源码级别流程分析
spring 源码中解决循环依赖的核心类是:DefaultSingletonBeanRegistry ,核心的代码如下:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 首先从一级缓存中获取对象
Object singletonObject = this.singletonObjects.get(beanName);
// 没有从一级缓存中获取到对象,并且当前对象正处于创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 上锁,防止出现线程安全问题
synchronized (this.singletonObjects) {
// 从二级缓存中获取对象
singletonObject = this.earlySingletonObjects.get(beanName);
// 从二级缓存中没有获取到对象,并且这个对象允许提前暴露
if (singletonObject == null && allowEarlyReference) {
// 从三级缓存中获取 ObjectFactory 对象
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 通过调用 ObjectFactory 的 getObject() 获取(并不完整的)对象
singletonObject = singletonFactory.getObject();
// 把获取到的对象保存的二级缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
// 从三级缓存中移除对象
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
spring 解决循环依赖的详细执行流程如下:(当然这里面也省略了很多细节性的步骤,因为这里我们主要关注解决循环依赖的关键执行步骤)
- 首先在创建 userService 对象时,会调用 getBean() ,然后调用 doGetBean() 方法
- doGetBean() 会调用无回调函数的 getSingleton(beanName) 获取 userService 对象
- getSingleton() 方法会从 singletopnObjects (一级缓存中获取 userService ),如果没有获取到,则判断是否当前正在创建这个 userService ,如果当前没有正在创建,则直接返回 null
- 然后进行一系列的操作,接着调用有回调函数的 getSingleton(beanName,createBean()) 创建 userService
- 在创建 userService 之前先标记当前 userService 正在创建中,再调用回调函数 createBean()
- 回调函数 createBean(),再调用 doCreateBean(),接着调用 createBeanInstance() 创建 userService
- 创建完成后,未进行属性自动注入之前(即:实例化阶段之后,初始化阶段之前),调用 addSingletonFactory(),将创建好的 userService 包装成 ObjectFactory 然后放入 singletonFactories(三级缓存)中
- 调用 populateBean() 进行属性自动注入,然后去创建需要自动注入的依赖对象 orderService
- 重复 (1-8 )步骤去创建 orderService
- 创建完 orderService 之后,调用 populateBean() 方法,进行依赖注入 userService
- 然后调用 getBean() (和前面的 1-3 步一样)获取 userService ,然后从 singletonFactories (三级缓存) 中获取 ObjectFactory
- 接着调用 ObjectFactory 的 getObject 方法,getObject() 方法会从三级缓存中获取 userService (此时的 userService 对象还不是一个完整的对象,它的 orderService 属性是为 null 的,因为还没有对 userService 执行自动注入的),然后将 userService 保存到 earlySingletonObjects(二级缓存)中,并从 singletonFactories(三级缓存)中移除
- 然后给 orderService 对象的 userService 属性赋值为二级缓存中保存的 userService 对象(这一步就是所谓的自动依赖注入了,虽然此时的 userService 还不是一个完整的对象,但是 orderService 的 userService 属性保存的也只是 userService 对象的引用地址而已,所以和 userService 当前是否为一个完整的对象是没有什么关系的,因为此时此刻,还没有人去用这个对象)
- 最后调用 initializeBean() 方法,完成 orderService 的最后初始化
- 最后再调用 addSingleton() 方法,将创建好并初始化好的 orderService 对象放入singletonObjects(一级缓存)中,并从三级缓存(singletonFactories )中移除 orderService
- 然后回到创建 userService 的生命周期中,继续给 userService 的 orderService 属性自动注入
- 最后结束 userService 的整个创建生命周期,并调用 addSingleton() 方法将 userService 从二级缓存中移除,并添加到一级缓存中
标签:缓存,依赖,对象,spring,调用,orderService,userService,三级 来源: https://blog.csdn.net/weixin_41106708/article/details/122237327