深入理解 Spring 循环依赖之三级缓存(附源码分析)

前言:

学过 Spring 的都知道 Spring 利用三级缓存解决了循环依赖问题,那你知道什么是循环依赖?什么又是三级缓存?本篇将从源码层面分析 Spring 是怎么去利用三级缓存帮我们解决循环依赖问题。

深入理解 Spring IOC 底层实现机制(refresh 方法源码分析)

Spring 源码之 BeanDefinition 加载分析

深入理解 Spring Bean 生命周期(附源码分析)

什么是循环依赖?

简单来说 如果 Bean A 依赖了 Bean B,而 Bean B 又依赖了 Bean A,造成了相互依赖,也就是我们常说的的循环依赖,代码演示如下:

@Service
public class A{

    @Resource
    private B b;
}

@Service
public class B{

    @Resource
    private A a ;
}

什么是三级缓存?

三级缓存是 Spring 为了解决循环依赖问题而设计的,在 Spring 源码中是三个 Map 存储,如下:

// 一级缓存 存放完整的Bean(实例化 初始化完成的 bean)
private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);

// 二级缓存Map 存放不完整的Bean(只实例化完 还没属性赋值、初始化)
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap(16);

// 三级缓存Map 存放一个Bean的lambda表达式(也是我们常说的早期bean)
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
  • 一级缓存(singletonObjects):用来存储成品 Bean 对象,也就是初始化完成可以直接被其他对象引用的对象。
  • 二级缓存(earlySingletonObjects):用来存储半成品对象,也就是实例化了但是还没有初始化的对象。
  • 三级缓存(singletonFactories):用来存储工厂对象,二级缓存就是从这个工厂中获取的对象,也就是一个 lambda 表达式,这个 lambda 表达式会提前暴露 Bean 对象的引用,执行这个 lambda 表达式会把这个引用放入二级缓存,同时删除三级缓存。

图解 Spring 三级缓存解决循环依赖:

我们用画图的方法来理解一下 Bean A 依赖 Bean B,Bean B又依赖 Bean A 的情况下,Spring 是怎么去进行 Bean A 和 Bean B 的加载的。

在这里插入图片描述

Spring 解决循环依赖的核心就是暴露早期对象,将对象的实例化和初始化分开。

循环依赖场景面试问题

源码分析部分较长,我们先把关于 Spring 三级缓存解决循环依赖的常见问题科普一下。

三个缓存对象的查找顺序是什么样子的?

这个问题阅读了源码的都知道是先找一级缓存,找不到再找二级缓存,最后才会找三级缓存。

一级缓存能否解决循环依赖问题?

不能,一级缓存和二级缓存存储的是不同类型的对象,如果只有一级缓存的话,那么成品对象和半成品对象会存放在一起,半成品状态的对象是直接接暴露给其他对象做引用的,放在一起就无法判断哪些是半成品对象那些事成品对象了。

二级缓存能否解决循环依赖问题?

可以解决某些情况下的循环依赖问题,但是有限制条件,不能出现代理对対象,例如 AOP 的场景、事务的场景。

为什么必须要使用三级缓存?

三级缓存的设计目的主要是针对 AOP 等需要代理场景的 Bean 对象,三级缓存是一个单例工厂,这个工厂的目的是延迟实例化阶段生成对象的代理,只有当 Bean 对象真正发生循环依赖时候,才会提前去生成代理对象,否则只会创建一个工厂放入三级缓存中,但是不会通过这个工厂去创建真正的对象,如果没有三级缓存的话,意味着所有 Bean 对象都需要在提前去生成代理对象,这违背了 Spring 的设计,Spring 设计之初是让 Bean 在生命周期的最后一步完成代理,而不是在实例化后就立马完成代理,Spring 结合 AOP 是通过 AnnotationAwareAspectJAutoProxyCreator 这个后置处理器来完成的,在这个后置处理的 postProcessAfterInitialization 方法中对初始化后的 Bean 完成 AOP 代理,如果出现了循环依赖,没有办法,只有给 Bean 先创建代理。

三级缓存为什么不能解决构造器引起的循环依赖?

因为构造器引起的循环依赖是发生在实例化阶段,而 Spring 使用一、二、三级缓存解决循环依赖的思想是把实例化和初始化分开,暴露早期实例化但是没有初始化的对象,构造器引起的循环依赖是发生在实例化阶段,自然就无法使用三级缓存来解决了。

Spring 三级缓存解决循环依赖源码分析

Spring 容器中的 Bean 获取是如下流程:

getBean–>doGetBean–>createBean–>doCreateBean
分析 Spring 使用三级缓存解决循环依赖,实际就是分析获取 Bean 的过程,当然这个过程包含创建 Bean,我们从 doGetBean 方法开始分析。

AbstractBeanFactory#doGetBean 方法源码分析

AbstractBeanFactory#doGetBean 方法在 Spring Bean 生命周期中分析过,本篇重点分析和三级缓存相关的点,比如 this.getSingleton(beanName) 方法。

//AbstractBeanFactory#doGetBean 方法
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
	//根据 name 获取beanName 如果是别名会将别名转换为规范的名称
	String beanName = this.transformedBeanName(name);
	//根据beanName 从容器中获取 bean 对象(包含一级缓存 二级缓存 三级缓存)  本篇分析的重点
	Object sharedInstance = this.getSingleton(beanName);
	Object bean;
	//bean 不为空 直接从IOC 容器中获取 bean
	if (sharedInstance != null && args == null) {
		if (this.logger.isTraceEnabled()) {
			if (this.isSingletonCurrentlyInCreation(beanName)) {
				this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
			} else {
				this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
			}
		}
		//对 bean 进行 BeanFactory 的相关操作(不是本次分析的重点)
		bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
	} else {
		//表示IOC 容器中没有当前单例 bean
		if (this.isPrototypeCurrentlyInCreation(beanName)) {
			//IOC 容器中正在创建原型bean 原型bean 中出现循环依赖直接抛出 bean 创建异常
			throw new BeanCurrentlyInCreationException(beanName);
		}
		//获取父级 BeanFactory  IOC 容器
		BeanFactory parentBeanFactory = this.getParentBeanFactory();
		if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
			//当前IOC容器的父容器存在 且当前容器中不存在当前beanName的 beanDefinition
			//解析指定 Bean 名称的原始名称
			String nameToLookup = this.originalBeanName(name);
			//父IOC 容器是 AbstractBeanFactory 
			if (parentBeanFactory instanceof AbstractBeanFactory) {
				//继续调用AbstractBeanFactory#doGetBean 方法查询单例bean
				return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
			}

			if (args != null) {
				//委派父级IOC 容器根据指定名称和显式的参数查找
				return parentBeanFactory.getBean(nameToLookup, args);
			}

			if (requiredType != null) {
				//委派父级IOC 容器根据指定名称和类型去查找
				return parentBeanFactory.getBean(nameToLookup, requiredType);
			}
			//委派父级IOC 容器根据指定名称去查找
			return parentBeanFactory.getBean(nameToLookup);
		}
		//bean 是否需要做类型验证 一般不需要
		if (!typeCheckOnly) {
			//不需要做类型检查的时候 标记知道beanName 已经在创建中
			this.markBeanAsCreated(beanName);
		}

		try {
			//根据指定 beanName 合并 beanDefinition 主要是处理子类 bean 继承父类 bean 的公共属性问题
			RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
			this.checkMergedBeanDefinition(mbd, beanName, args);
			//获取当前bean 的所有依赖bean 名称
			String[] dependsOn = mbd.getDependsOn();
			String[] var11;
			//当前bean 依赖的bean 是否为空 不为空 优先创建依赖bean
			if (dependsOn != null) {
				var11 = dependsOn;
				int var12 = dependsOn.length;

				for(int var13 = 0; var13 < var12; ++var13) {
					String dep = var11[var13];
					//是否存在循环依赖 存在就报异常
					if (this.isDependent(beanName, dep)) {
						throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
					}
					//注册各个bean 之间的关系 方便bean 销毁
					this.registerDependentBean(dep, beanName);

					try {
						//创建依赖的bean
						this.getBean(dep);
					} catch (NoSuchBeanDefinitionException var24) {
						throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
					}
				}
			}
			//是否是单例bean
			if (mbd.isSingleton()) {
				//创建bean 对象 并注册给所有依赖的bean 加入 Spring 一级缓存 并从二级 三级缓存中删除
				sharedInstance = this.getSingleton(beanName, () -> {
					try {
						//创建单例bean createBean 方法是重点方法
						return this.createBean(beanName, mbd, args);
					} catch (BeansException var5) {
						//创建失败显式地从单例缓存中删除实例
						this.destroySingleton(beanName);
						throw var5;
					}
				});
				//获取指定的bean实例对象
				bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
			} else if (mbd.isPrototype()) {
				//原型bean 每次都会创建一个新的对象
				var11 = null;

				Object prototypeInstance;
				try {
					//注册当前创建的原型bean 对象
					this.beforePrototypeCreation(beanName);
					//创建bean createBean 方法是重点方法
					prototypeInstance = this.createBean(beanName, mbd, args);
				} finally {
					//异常回调 告诉容器 指定的bean 不再创建
					this.afterPrototypeCreation(beanName);
				}
				//获取指定的bean实例对象
				bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
			} else {
				//既不是单例bean 也不是原型bean 根据bean 定义的作用域来创建bean
				//获取bean的作用域(一般分为单例、原型、request、session、application、)
				String scopeName = mbd.getScope();
				//获取指定 bean 的作用域
				Scope scope = (Scope)this.scopes.get(scopeName);
				if (scope == null) {
					//bean 作用域为空 抛出异常
					throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
				}

				try {
					//匿名内部类 获取一个指定作用域的 bean
					Object scopedInstance = scope.get(beanName, () -> {
						//注册当前创建的bean 对象
						this.beforePrototypeCreation(beanName);

						Object var4;
						try {
							//创建bean createBean 方法是重点方法
							var4 = this.createBean(beanName, mbd, args);
						} finally {
							//异常回调 告诉容器 指定的bean 不再创建
							this.afterPrototypeCreation(beanName);
						}

						return var4;
					});
					//获取指定的bean实例对象
					bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
				} catch (IllegalStateException var23) {
					throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", var23);
				}
			}
		} catch (BeansException var26) {
			//bean 创建失败后的清理bean 工作
			this.cleanupAfterBeanCreationFailure(beanName);
			throw var26;
		}
	}


	//检查bean 的类型
	//类型不为空 且bean 不是当前类型
	if (requiredType != null && !requiredType.isInstance(bean)) {
		try {
			//获取bean 的类型转换器 并将类型转换为 requiredType
			T convertedBean = this.getTypeConverter().convertIfNecessary(bean, requiredType);
			if (convertedBean == null) {
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			} else {
				return convertedBean;
			}
		} catch (TypeMismatchException var25) {
			if (this.logger.isTraceEnabled()) {
				this.logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var25);
			}

			throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
		}
	} else {
		return bean;
	}
}

DefaultSingletonBeanRegistry#getSingleton(String beanName) 方法源码分析

DefaultSingletonBeanRegistry#getSingleton 方法主要是依次从 Spring 的一、二、三级缓存中获取 Bean 对象,需要注意的是容器启动时候第一次调用 doGetBean 的时候,从 Spring 的一、二、三级缓存中是获取不到 Bean 对象的,
我们继续往下看 this.createBean(beanName, mbd, args) 方法中的 this.doCreateBean(beanName, mbdToUse, args) 方法,doCreateBean 方法真正干活的方法。

//从 Spring IOC 容器中获取单例 bean 方法包装调用  没有实际操作
@Nullable
public Object getSingleton(String beanName) {
	return this.getSingleton(beanName, true);
}

//从 Spring 三级缓存中获取单例 bean
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	//从一级缓存中获取 bean
	Object singletonObject = this.singletonObjects.get(beanName);
	//如果一级缓存中获取的bean 为空 且bean 正在创建中
	if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
		//加同步锁
		synchronized(this.singletonObjects) {
			//从二级缓存中获取 bean
			singletonObject = this.earlySingletonObjects.get(beanName);
			//二级缓存中bean为空 且bean 允许早期引用
			if (singletonObject == null && allowEarlyReference) {
				//从三级缓存中获取bean(是lambda表达式)
				ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					//三级缓存中获取的bean 不为空 执行lambda 表达式 得到半成品的 bean
					singletonObject = singletonFactory.getObject();
					//将半成品的bean 放进二级缓存
					this.earlySingletonObjects.put(beanName, singletonObject);
					//将三级缓存的bean移出
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}

	return singletonObject;
}

DefaultSingletonBeanRegistry#getSingleton (String beanName, ObjectFactory<?> singletonFactory)方法源码分析

当前 getSingleton 方法和上一个 getSingleton 方法的区别在于当前方法会执行 lambda 表达式,并将对象直接从三级缓存加入到一级缓存,并从三级缓存中清除当前对象。

//从 Spring 容器中获取 Bean
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	Assert.notNull(beanName, "Bean name must not be null");
	//同步防止线程安全问题 因为创建过程中也在操作singletonObjects
	synchronized(this.singletonObjects) {
		//从一级缓存中获取 bean
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null) {
			//一级缓存中没有获取到bean
			//bean 正在销毁 则抛出异常 bean不允许被创建
			if (this.singletonsCurrentlyInDestruction) {
				throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
			}

			if (this.logger.isDebugEnabled()) {
				this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
			}
			//bean 创建前的准备工作
			this.beforeSingletonCreation(beanName);
			//bean 创建状态的标记
			boolean newSingleton = false;
			//异常标记
			boolean recordSuppressedExceptions = this.suppressedExceptions == null;
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = new LinkedHashSet();
			}

			try {
				//回调方式创建bean 核心
				singletonObject = singletonFactory.getObject();
				//标记bean 已经被创建
				newSingleton = true;
			} catch (IllegalStateException var16) {
				singletonObject = this.singletonObjects.get(beanName);
				if (singletonObject == null) {
					throw var16;
				}
			} catch (BeanCreationException var17) {
				BeanCreationException ex = var17;
				if (recordSuppressedExceptions) {
					Iterator var8 = this.suppressedExceptions.iterator();

					while(var8.hasNext()) {
						Exception suppressedException = (Exception)var8.next();
						ex.addRelatedCause(suppressedException);
					}
				}

				throw ex;
			} finally {
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = null;
				}
				//单例bean 创建后的处理方法调用 例如删除bean正在创建的记录
				this.afterSingletonCreation(beanName);
			}

			if (newSingleton) {
				//是新创建的bean 加入一级缓存
				this.addSingleton(beanName, singletonObject);
			}
		}

		return singletonObject;
	}
}

//单例bean 加入一级缓存
protected void addSingleton(String beanName, Object singletonObject) {
	//同步防止线程安全问题
	synchronized(this.singletonObjects) {
		//bean 对象加入一级缓存
		this.singletonObjects.put(beanName, singletonObject);
		//bean 对象从三级缓存中移出
		this.singletonFactories.remove(beanName);
		//bean 对象从二级缓存中移出
		this.earlySingletonObjects.remove(beanName);
		//注册bean
		this.registeredSingletons.add(beanName);
	}
}

AbstractAutowireCapableBeanFactory#doCreateBean方法源码分析

doCreateBean 在 Spring Bean 生命周期中分析过,本次重点关注 DefaultSingletonBeanRegistry#addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory)、AbstractAutowireCapableBeanFactory#populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)和
DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean) 方法。

//AbstractAutowireCapableBeanFactory#doCreateBean
//真正创建Bean的方法
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
	//实例bean 的包装对象 beanWrapper 其实就是对bean 的包装
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		//如果是单例bean 从 factoryBean 的缓存中移除当前bean (有可能在本Bean创建之前 就有其他Bean把当前Bean给创建出来了 比如依赖注入过程中)
		instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
	}

	if (instanceWrapper == null) {
		//根据beanName、bean的定义信息、args创建一个新的实例对象  根据指定bean使用对应的策略创建新的实例 工厂方法 构造函数自动注入 简单实例化  底层使用 cglib代理 和 反射生成实例对象
		instanceWrapper = this.createBeanInstance(beanName, mbd, args);
	}
	//获取 instanceWrapper 包装的 bean 实例
	Object bean = instanceWrapper.getWrappedInstance();
	//获取 instanceWrapper 包装的 class
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}
	
	//加锁 保证线程安全
	synchronized(mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			try {
				//允许后置处理器修改合并后的 beanDefinition 将 工厂中的所有 MergedBeanDefinitionPostProcessors 应用到mbd  调用这些后处理器的 postProcessMergedBeanDefinition 方法
				this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			} catch (Throwable var17) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
			}
			//标记该 beanDefinition 已经应用过 工厂中的所有 MergedBeanDefinitionPostProcessors
			mbd.postProcessed = true;
		}
	}

	//判断是否需要暴露早期单例对象(解决循环依赖问题)
	//单例对象 允许循环引用 单例对象正在创建中 满足三个条件 则需要暴露早期单例对象
	boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
	if (earlySingletonExposure) {
		//需要暴露早期单例对象
		if (this.logger.isTraceEnabled()) {
			this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
		}
		//这里创建了一个匿名的ObjectFactory 工厂 可以用来获取对象
		//addSingletonFactory 方法会将这个 匿名的ObjectFactory 工厂 放入到 singletonFactories 中 singletonFactories 是 Spring 的三级缓存
		//为了避免循环依赖 尽早的持有对象的引用
		//本次重点关注的方法 三级缓存
		this.addSingletonFactory(beanName, () -> {
			return this.getEarlyBeanReference(beanName, mbd, bean);
		});
	}

	//Bean对象的初始化 依赖注入在此触发
	//这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean
	Object exposedObject = bean;

	try {
		//bean 的属性填充 将bean 对象的实例封装 将Bean定义中配置的属性值赋值给实例对象 包括依赖的 bean 
		this.populateBean(beanName, mbd, instanceWrapper);
		//bean 的初始化 包括应用工厂回调以及init方法和BeanPostProcessors
		exposedObject = this.initializeBean(beanName, exposedObject, mbd);
	} catch (Throwable var18) {
		if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
			throw (BeanCreationException)var18;
		}

		throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
	}

	//第二次解决循环依赖问题
	if (earlySingletonExposure) {
		//需要暴露早期对象
		//从一级 二级缓存中获取bean 对象
		//把对象加入到二级缓存中本次重点分析的方法
		Object earlySingletonReference = this.getSingleton(beanName, false);
		if (earlySingletonReference != null) {
			//bean 对象不为空 根据名称获取的已注册的Bean和正在实例化的Bean是同一个
			if (exposedObject == bean) {
				//当前实例化的Bean初始化完成
				exposedObject = earlySingletonReference;
			} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
				//当前Bean依赖其他Bean 并且当发生循环引用时不允许新创建实例对象
				//获取当前bean 依赖的其他bean
				String[] dependentBeans = this.getDependentBeans(beanName);
				//实际依赖的bean
				Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
				String[] var12 = dependentBeans;
				int var13 = dependentBeans.length;
				//遍历依赖的bean
				for(int var14 = 0; var14 < var13; ++var14) {
					String dependentBean = var12[var14];
					//删除给定Bean名称的单例实例 但仅当它没有用于类型检查之外的其他目的时才删除
					if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
						//没有删除的bean 加入到实际依赖的bean 中
						actualDependentBeans.add(dependentBean);
					}
				}
				//因为bean创建后其所依赖的bean一定是已经创建的 actualDependentBeans不为空则表示当前的bean创建后其依赖的bean却没有全部创建完 说明勋在循环依赖
				if (!actualDependentBeans.isEmpty()) {
					throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
				}
			}
		}
	}

	try {
		//注册为一次性的bean 也就是处理Bean销毁前要执行的方法
		this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
		return exposedObject;
	} catch (BeanDefinitionValidationException var16) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
	}
}

DefaultSingletonBeanRegistry#addSingletonFactory 方法源码分析

DefaultSingletonBeanRegistry#addSingletonFactory 方法只做了一件事,就是把早期 Bean 对象放入三级缓存。

//添加单例bean对象到三级缓存
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
	Assert.notNull(singletonFactory, "Singleton factory must not be null");
	//同步防止线程安全问题
	synchronized(this.singletonObjects) {
		if (!this.singletonObjects.containsKey(beanName)) {
			//三级缓存中不存在 bean 对象 bean 对象加入三级缓存 
			this.singletonFactories.put(beanName, singletonFactory);
			//从二级缓存中移出 bean 对象
			this.earlySingletonObjects.remove(beanName);
			//注册单例bean 
			this.registeredSingletons.add(beanName);
		}

	}
}

AbstractAutowireCapableBeanFactory#populateBean方法源码分析

populateBean 方法就是给对象属性赋值,在 Spring Bean 生命周期中也分析过,本次我们主要分析 populateBean 方法中的 this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs) 这行代码,也就是 AbstractAutowireCapableBeanFactory#applyPropertyValues 方法。

//AbstractAutowireCapableBeanFactory#populateBean
//将bean 属性设置到生成的实例对象上
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	if (bw == null) {
		//BeanWrapper 为空 且有依赖的属性 直接抛异常
		if (mbd.hasPropertyValues()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
		}
	} else {
		//在设置属性之前 给任何InstantiationAwareBeanPostProcessors一个修改bean状态的机会
		if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
			Iterator var4 = this.getBeanPostProcessorCache().instantiationAware.iterator();

			while(var4.hasNext()) {
				InstantiationAwareBeanPostProcessor bp = (InstantiationAwareBeanPostProcessor)var4.next();
				if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					return;
				}
			}
		}

		//获取容器在解析Bean定义资源时为BeanDefiniton中设置的属性值
		PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;
		//依赖注入的逻辑
		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == 1 || resolvedAutowireMode == 2) {
			//MutablePropertyValues是PropertyValues具体的实现类
			MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
			if (resolvedAutowireMode == 1) {
				//ByName
				this.autowireByName(beanName, mbd, bw, newPvs);
			}

			if (resolvedAutowireMode == 2) {
				//ByType
				this.autowireByType(beanName, mbd, bw, newPvs);
			}

			pvs = newPvs;
		}
		// 获取是否有实现InstantiationAwareBeanPostProcessor的方法 这里主要使用postProcessProperties方法。
		boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
		// 获取是否需要进行依赖注入
		boolean needsDepCheck = mbd.getDependencyCheck() != 0;
		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) {
			if (pvs == null) {
				// 属性为空 从beanDefinition中获取需要注入的信息
				pvs = mbd.getPropertyValues();
			}

			PropertyValues pvsToUse;
			for(Iterator var9 = this.getBeanPostProcessorCache().instantiationAware.iterator(); var9.hasNext(); pvs = pvsToUse) {
				//这里会调用AutowiredAnnotationBeanPostProcessor的 postProcessProperties()方法 会直接给对象中的属性赋值 真正的处理@Autowired @Resource @Value 等注解
				//AutowiredAnnotationBeanPostProcessor内部并不会处理pvs。直接返回自己设置的PropertyValues对象(可以在实例化前设置)。
				InstantiationAwareBeanPostProcessor bp = (InstantiationAwareBeanPostProcessor)var9.next();
				//这里的含义是程序员自己已经给属性赋值了,就不需要Spring给他赋值。这里是程序员没有赋值,所以需要Spring进行赋值
				pvsToUse = bp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					if (filteredPds == null) {
						filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
					}
					//设置值
					pvsToUse = bp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						return;
					}
				}
			}
		}
		//是否需要属性注入
		if (needsDepCheck) {
			if (filteredPds == null) {
				//为空 则初始化
				filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			//检查依赖
			this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
		}

		if (pvs != null) {
			//应用给定的属性值 解决任何在这个bean工厂运行时其他bean的引用 必须使用深拷贝 所以我们不会永久地修改这个属性
			this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
		}

	}
}

AbstractAutowireCapableBeanFactory#applyPropertyValues 方法源码分析

AbstractAutowireCapableBeanFactory#applyPropertyValues 方法很长,作用是应用给定的属性值,解决任何在这个 bean 工厂运行时其他bean的引用必须使用深拷贝,所以我们不会永久地修改这个属性,关于这些功能我们不需要要关注那么多,重点关注 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue) 这行代码,我们接着看。

//应用给定的属性值 解决任何在这个bean工厂运行时其他bean的引用 必须使用深拷贝 所以我们不会永久地修改这个属性
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
	//PropertyValues 是否有属性判断 没有属性不处理
	if (!pvs.isEmpty()) {
		//如果有安全控制 且 bw 是 BeanWrapperImpl 的实例
		if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
			//设置 BW 安全上下文为访问控制山下文
			((BeanWrapperImpl)bw).setSecurityContext(this.getAccessControlContext());
		}
		//MutablePropertyValues 是 PropertyValues接口的默认实现 允许对属性进行简单操作 并提供构造函数来支持从映射 进行深度复制和构造等
		MutablePropertyValues mpvs = null;
		//原始属性值列表
		List original;
		//判断 pvs 是否是 MutablePropertyValues
		if (pvs instanceof MutablePropertyValues) {
			//是就强转
			mpvs = (MutablePropertyValues)pvs;
			//mpvs 是否需要转换
			if (mpvs.isConverted()) {
				try {
					//设置属性值
					bw.setPropertyValues(mpvs);
					return;
				} catch (BeansException var18) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", var18);
				}
			}
			//获取 mpvs 属性列表
			original = mpvs.getPropertyValueList();
		} else {
			//获取 pvs 属性列表
			original = Arrays.asList(pvs.getPropertyValues());
		}
		//获取工厂自定义类型转换器
		TypeConverter converter = this.getCustomTypeConverter();
		if (converter == null) {
			converter = bw;
		}
		//BeanDefinition 解析
		BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, (TypeConverter)converter);
		//创建一个深拷贝
		List<PropertyValue> deepCopy = new ArrayList(original.size());
		//是否需要解析标志
		boolean resolveNecessary = false;
		//迭代遍历
		Iterator var11 = original.iterator();

		while(true) {
			while(var11.hasNext()) {
				//获取 PropertyValue
				PropertyValue pv = (PropertyValue)var11.next();
				if (pv.isConverted()) {
					//已经转换 直接加入到 深拷贝中
					deepCopy.add(pv);
				} else {
					//获取 pv 属性名称
					String propertyName = pv.getName();
					//获取 pv 属性值
					Object originalValue = pv.getValue();
					//是否 自动生成标记的规范实例
					if (originalValue == AutowiredPropertyMarker.INSTANCE) {
						//获取写方法(set)
						Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
						if (writeMethod == null) {
							//写方法为空 抛出异常
							throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
						}
						//将 writeMethod 封装到 DependencyDescriptor 中
						originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
					}
					// valueResolver 根据 pv 解析出 originalValue 所封装的对象 重点方法(循环依赖的对象从这里进去)
					Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
					//解析出来的值
					Object convertedValue = resolvedValue;
					//可转换标记 propertyName 是否 在bw中的可写属性 
					//prepertyName不是表示索引属性或嵌套属性
					boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
					//是否可转换
					if (convertible) {
						//将 resolvedValue 转换为指定的目标属性对象
						convertedValue = this.convertForProperty(resolvedValue, propertyName, bw, (TypeConverter)converter);
					}
					//resolvedValue 与 originalValue 是否同一个对象
					if (resolvedValue == originalValue) {
						//是否可转换
						if (convertible) {
							// convertedValue 设置 给 PV
							pv.setConvertedValue(convertedValue);
						}
						//加入到 deepCopy 中
						deepCopy.add(pv);
					} else if (convertible && originalValue instanceof TypedStringValue && !((TypedStringValue)originalValue).isDynamic() && !(convertedValue instanceof Collection) && !ObjectUtils.isArray(convertedValue)) {
						pv.setConvertedValue(convertedValue);
						deepCopy.add(pv);
					} else {
						//标记为还需要解析
						resolveNecessary = true;
						//构建对象 加入到 deepCopy 中
						deepCopy.add(new PropertyValue(pv, convertedValue));
					}
				}
			}
			
			if (mpvs != null && !resolveNecessary) {
				//mpvs 不为空 且 不需要再解析 	将此 holder 标记为只包含转换后的值
				mpvs.setConverted();
			}

			try {
				//使用 deepCopy 构造一个新的 MutablePropertyValues 对象 设置到 bw 中以对 bw 的属性值更新
				bw.setPropertyValues(new MutablePropertyValues(deepCopy));
				return;
			} catch (BeansException var19) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", var19);
			}
		}
	}
}

BeanDefinitionValueResolver#resolveValueIfNecessary 方法源码分析

BeanDefinitionValueResolver#resolveValueIfNecessary 方法主要是对参数进行判断后继续调用方法。

//给定一个PropertyValue 返回一个值 必要时解析对工厂中其他bean的引用
@Nullable
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
	//是否是运行是 bean 引用
	if (value instanceof RuntimeBeanReference) {
		//循环依赖是运行时 bean 引用  循环依赖分析的重点
		RuntimeBeanReference ref = (RuntimeBeanReference)value;
		return this.resolveReference(argName, ref);
	} else if (value instanceof RuntimeBeanNameReference) {
		String refName = ((RuntimeBeanNameReference)value).getBeanName();
		refName = String.valueOf(this.doEvaluate(refName));
		if (!this.beanFactory.containsBean(refName)) {
			throw new BeanDefinitionStoreException("Invalid bean name '" + refName + "' in bean reference for " + argName);
		} else {
			return refName;
		}
	} else if (value instanceof BeanDefinitionHolder) {
		BeanDefinitionHolder bdHolder = (BeanDefinitionHolder)value;
		return this.resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
	} else if (value instanceof BeanDefinition) {
		BeanDefinition bd = (BeanDefinition)value;
		String innerBeanName = "(inner bean)#" + ObjectUtils.getIdentityHexString(bd);
		return this.resolveInnerBean(argName, innerBeanName, bd);
	} else {
		//非重点 不分析
	}
}

BeanDefinitionValueResolver#resolveReference 方法源码分析

BeanDefinitionValueResolver#resolveReference 让我们看到熟悉的 getBean 方法,如果 Bean A 依赖了 Bean B,而 Bean B 又依赖了 Bean A,假设 Bean A 先创建,那这里的 getBean 方法就是去获取 Bean B,也就是重新走一遍 Bean A 的流程,循环依赖的循环来了。

//解析应用的属性值
@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
	try {
		//获取 bean 类型
		Class<?> beanType = ref.getBeanType();
		Object bean;
		//引用对象是否在父容器中 在父容器中 就从父容器获取对象
		if (ref.isToParent()) {
			BeanFactory parent = this.beanFactory.getParentBeanFactory();
			if (parent == null) {
				throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean " + ref + " in parent factory: no parent factory available");
			}

			if (beanType != null) {
				bean = parent.getBean(beanType);
			} else {
				bean = parent.getBean(String.valueOf(this.doEvaluate(ref.getBeanName())));
			}
		} else {
			//不在父容器中
			String resolvedName;
			if (beanType != null) {
				NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);
				bean = namedBean.getBeanInstance();
				resolvedName = namedBean.getBeanName();
			} else {
				//获取 resolvedName 引用包装的 bean 名称
				resolvedName = String.valueOf(this.doEvaluate(ref.getBeanName()));
				//获取 resolvedName 的bean 对象--此处重点来了 又看到 getBean 方法了 熟悉的感觉来了
				bean = this.beanFactory.getBean(resolvedName);
			}

			this.beanFactory.registerDependentBean(resolvedName, this.beanName);
		}

		if (bean instanceof NullBean) {
			bean = null;
		}

		return bean;
	} catch (BeansException var7) {
		throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, var7);
	}
}

DefaultSingletonBeanRegistry#getSingleton方法源码分析

DefaultSingletonBeanRegistry#getSingleton方法主要就是从三级缓存获取到对象,执行 lambda 表达式,并把得到的对象放入到二级缓存中,同时删除三级缓存的对象,DefaultSingletonBeanRegistry#getSingleton 方法中获取的 bean 对象和 DefaultSingletonBeanRegistry#addSingletonFactory 方法中的 Bean 对象的区别是两个方法之间是调用了 populateBean 方法的,也就是精力属性赋值,对象的属性值是有变化的。

//从缓存中获取 bean 对象
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	//从一级缓存中获取对象
	Object singletonObject = this.singletonObjects.get(beanName);
	//一级缓缓存中没有获取到对象且单例对象正在创建中
	if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
		//同步防止线程安全问题
		synchronized(this.singletonObjects) {
			//从二级缓存中获取对象
			singletonObject = this.earlySingletonObjects.get(beanName);
			//二级缓存中对象为空且bean 对象允许暴露早期引用
			if (singletonObject == null && allowEarlyReference) {
				//从三级缓存中获取bean 对象(获取到的是lambda表达式)
				ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					//执行lambda表达式 也是回调 获取到 bean 对象
					singletonObject = singletonFactory.getObject();
					//bean 对象保存到二级缓存中(半成品对象)--这里的对象是经过了 populateBean 属性赋值的
					this.earlySingletonObjects.put(beanName, singletonObject);
					//从三级缓存中移出早期对象
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}

	return singletonObject;
}

至此,Spring 三级缓存相关源码已经分析完毕,希望可以帮助到有需要的小伙伴。

欢迎提出建议及对错误的地方指出纠正。

  • 33
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring循环依赖三级缓存是指在实例化Bean的过程中,Spring框架内部维护了三个缓存Map,分别是singletonObjects、earlySingletonObjects和singletonFactories。 1. singletonObjects缓存:存放已经完全初始化的Bean实例,包括在初始化过程中有循环依赖的Bean 2. earlySingletonObjects缓存:存放已经进行了实例化但是还未完成初始化的Bean实例,也包括在初始化过程中有循环依赖的Bean 3. singletonFactories缓存:存放Bean实例的Factory对象,用于解决循环依赖的问题,当需要解决循环依赖时,由Factory对象提供未完成的Bean实例。 通过这三个缓存,Spring框架可以在Bean实例化的过程中解决循环依赖的问题。当Bean A依赖Bean B,同时Bean B也依赖Bean A时,Spring框架会通过缓存机制来避免无限递归的循环依赖。具体流程如下: 1. 当需要实例化Bean A时,Spring框架会先从singletonObjects缓存中查找是否已经存在该Bean实例,如果存在,则直接返回该实例。 2. 如果singletonObjects缓存中不存在Bean A实例,则会从earlySingletonObjects缓存中查找是否存在该实例。如果存在,则将其提供给Factory对象创建Bean A实例并返回。 3. 如果earlySingletonObjects缓存中也不存在Bean A实例,则会从singletonFactories缓存中查找是否存在该实例的Factory对象,如果存在,则使用该Factory对象创建Bean A实例并返回。 4. 如果singletonFactories缓存中也不存在Bean A实例的Factory对象,则需要创建一个新的Factory对象,同时将其存放到singletonFactories缓存中。这个新的Factory对象会提供一个未进行初始化的Bean A实例,同时缓存到earlySingletonObjects中。 5. 当Bean A实例被完全初始化后,会将其从earlySingletonObjects缓存中移动到singletonObjects缓存中,以供其他Bean依赖使用。 通过三级缓存的机制,Spring框架可以解决循环依赖的问题,并在Bean实例化过程中避免无限递归的循环依赖

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值