spring三级缓存解决循环依赖

spring三级缓存解决循环依赖,第1张

spring三级缓存解决循环依赖

spring三级缓存解决循环依赖
  • 前言
  • 一、循环依赖
  • 二、三级缓存
  • 三、spring解决循环依赖源码级别流程分析


前言

    我们都知道,在spring中属性的赋值是通过自动注入完成的,那么在自动注入的过程中它又是如何解决循环依赖的呢?


提示:本篇文章属于原创,请勿抄袭。

一、循环依赖

    要搞明白spring是如何解决循环依赖,首先我们要弄明白什么是循环依赖,如图所示:

    有两个 service 对象,分别是 userService 和 orderService,它们各自都有一个引用对方的属性,互相循环引用着对方。

二、三级缓存

    在 spring 中,解决循环依赖主要是通过三级缓存来实现的,它们分别是:

  1. singletonObjects (一级缓存)
  2. earlySingletonObjects (二级缓存)
  3. singletonFactories (三级缓存)

对应的源码如下:

	// 一级缓存,存放的是已经实例化,并且初始化后的单例对象(也叫单例池)
	private final Map singletonObjects = new ConcurrentHashMap<>(256);
	
	
	// 三级缓存,存放的是 ObjectFactory,通过 ObjectFactory 的 getObject()可以拿到已经实例化,但是并未初始化的对象
	private final Map> singletonFactories = new HashMap<>(16);


	// 二级缓存,存放的是已经实例化,但是并未初始化的对象
	private final Map 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 解决循环依赖的详细执行流程如下:(当然这里面也省略了很多细节性的步骤,因为这里我们主要关注解决循环依赖的关键执行步骤)

  1. 首先在创建 userService 对象时,会调用 getBean() ,然后调用 doGetBean() 方法
  2. doGetBean() 会调用无回调函数的 getSingleton(beanName) 获取 userService 对象
  3. getSingleton() 方法会从 singletopnObjects (一级缓存中获取 userService ),如果没有获取到,则判断是否当前正在创建这个 userService ,如果当前没有正在创建,则直接返回 null
  4. 然后进行一系列的 *** 作,接着调用有回调函数的 getSingleton(beanName,createBean()) 创建 userService
  5. 在创建 userService 之前先标记当前 userService 正在创建中,再调用回调函数 createBean()
  6. 回调函数 createBean(),再调用 doCreateBean(),接着调用 createBeanInstance() 创建 userService
  7. 创建完成后,未进行属性自动注入之前(即:实例化阶段之后,初始化阶段之前),调用 addSingletonFactory(),将创建好的 userService 包装成 ObjectFactory 然后放入 singletonFactories(三级缓存)中
  8. 调用 populateBean() 进行属性自动注入,然后去创建需要自动注入的依赖对象 orderService
  9. 重复 (1-8 )步骤去创建 orderService
  10. 创建完 orderService 之后,调用 populateBean() 方法,进行依赖注入 userService
  11. 然后调用 getBean() (和前面的 1-3 步一样)获取 userService ,然后从 singletonFactories (三级缓存) 中获取 ObjectFactory
  12. 接着调用 ObjectFactory 的 getObject 方法,getObject() 方法会从三级缓存中获取 userService (此时的 userService 对象还不是一个完整的对象,它的 orderService 属性是为 null 的,因为还没有对 userService 执行自动注入的),然后将 userService 保存到 earlySingletonObjects(二级缓存)中,并从 singletonFactories(三级缓存)中移除
  13. 然后给 orderService 对象的 userService 属性赋值为二级缓存中保存的 userService 对象(这一步就是所谓的自动依赖注入了,虽然此时的 userService 还不是一个完整的对象,但是 orderService 的 userService 属性保存的也只是 userService 对象的引用地址而已,所以和 userService 当前是否为一个完整的对象是没有什么关系的,因为此时此刻,还没有人去用这个对象
  14. 最后调用 initializeBean() 方法,完成 orderService 的最后初始化
  15. 最后再调用 addSingleton() 方法,将创建好并初始化好的 orderService 对象放入singletonObjects(一级缓存)中,并从三级缓存(singletonFactories )中移除 orderService
  16. 然后回到创建 userService 的生命周期中,继续给 userService 的 orderService 属性自动注入
  17. 最后结束 userService 的整个创建生命周期,并调用 addSingleton() 方法将 userService 从二级缓存中移除,并添加到一级缓存中

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5686448.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存