前言:
学过 Spring 的都知道 Spring 利用三级缓存解决了循环依赖问题,那你知道什么是循环依赖?什么又是三级缓存?本篇将从源码层面分析 Spring 是怎么去利用三级缓存帮我们解决循环依赖问题。
深入理解 Spring IOC 底层实现机制(refresh 方法源码分析)
Spring 源码之 BeanDefinition 加载分析
深入理解 Spring Bean 生命周期(附源码分析)
什么是循环依赖?
简单来说 如果 Bean A 依赖了 Bean B,而 Bean B 又依赖了 Bean A,造成了相互依赖,也就是我们常说的的循环依赖,代码演示如下:
@Service
public class A{@Resourceprivate B b;
}@Service
public class B{@Resourceprivate 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 容器中获取 beanif (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 容器中没有当前单例 beanif (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 方法查询单例beanreturn ((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 是否为空 不为空 优先创建依赖beanif (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 {//创建依赖的beanthis.getBean(dep);} catch (NoSuchBeanDefinitionException var24) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);}}}//是否是单例beanif (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 {//匿名内部类 获取一个指定作用域的 beanObject 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 的类型转换器 并将类型转换为 requiredTypeT 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 方法源码分析
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) {//从一级缓存中获取 beanObject singletonObject = this.singletonObjects.get(beanName);//如果一级缓存中获取的bean 为空 且bean 正在创建中if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {//加同步锁synchronized(this.singletonObjects) {//从二级缓存中获取 beansingletonObject = this.earlySingletonObjects.get(beanName);//二级缓存中bean为空 且bean 允许早期引用if (singletonObject == null && allowEarlyReference) {//从三级缓存中获取bean(是lambda表达式)ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);if (singletonFactory != null) {//三级缓存中获取的bean 不为空 执行lambda 表达式 得到半成品的 beansingletonObject = singletonFactory.getObject();//将半成品的bean 放进二级缓存this.earlySingletonObjects.put(beanName, singletonObject);//将三级缓存的bean移出this.singletonFactories.remove(beanName);}}}}return singletonObject;
}
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 包装的 classClass<?> 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 已经应用过 工厂中的所有 MergedBeanDefinitionPostProcessorsmbd.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在初始化完成之后返回作为依赖注入完成后的BeanObject exposedObject = bean;try {//bean 的属性填充 将bean 对象的实例封装 将Bean定义中配置的属性值赋值给实例对象 包括依赖的 bean this.populateBean(beanName, mbd, instanceWrapper);//bean 的初始化 包括应用工厂回调以及init方法和BeanPostProcessorsexposedObject = 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 依赖的其他beanString[] dependentBeans = this.getDependentBeans(beanName);//实际依赖的beanSet<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);String[] var12 = dependentBeans;int var13 = dependentBeans.length;//遍历依赖的beanfor(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) {//ByNamethis.autowireByName(beanName, mbd, bw, newPvs);}if (resolvedAutowireMode == 2) {//ByTypethis.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 是否是 MutablePropertyValuesif (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()) {//获取 PropertyValuePropertyValue 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 设置 给 PVpv.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 三级缓存相关源码已经分析完毕,希望可以帮助到有需要的小伙伴。
欢迎提出建议及对错误的地方指出纠正。