吃透Spring源码(十三):Spring循环依赖源码分析

一,循环依赖

1,什么是循环依赖

循环依赖其实就是循环引用,也就是两个或则两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于C,C又依赖于A。

在Spring中一般分为构造器循环依赖filed属性循环依赖

2,构造器循环依赖

实例化A对象需要依赖B对象,实例化B对象需要依赖A对象,所以最终两个都实例化不了。

@Component
public class A {

    private B b;

    public A(B b) {
        this.b = b;
    }
}

@Component
public class B {

    private A a;

    public B(A a) {
        this.a = a;
    }
}

Spring是无法解决构造期循环依赖的。

3,filed属性循环依赖

实例化A对象和实例化B对象之间并不相互影响,Spring是可以解决此种循环依赖的。

@Component
public class A {
    @Autowired
    private B b;
}

@Component
public class B {
    @Autowired
    private A a;
}

4,Spring是怎么解决循环依赖的?

三级缓存:

// 一级缓存,保存完整对象
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 二级缓存,保存实例化并未初始化的对象
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
// 三级缓存,保存ObjectFactory表达式,用于解决Aop
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

大致思想是:

  1. 实例化A对象,放入三级缓存,填充属性b,从容器中查找B对象,发现此时容器中没有B对象;
  2. 实例化B对象,放入三级缓存,填充属性a,从容器中查找A对象;
  3. 从三级缓存取到A对象,放入二级缓存,赋值给属性a,完成B对象的创建,把B对象放入一级缓存;
  4. 拿到完整B对象对A对象中的b属性赋值,完成A对象的创建,把A对象放入一级缓存。

二,源码探究Spring解决循环依赖过程

1,例子准备

A,B 类

public class A {
    @Autowired
    private B b;
}

public class B {
    @Autowired
    private A a;
}

配置类

@Configuration
public class CycleConfiguration {

    @Bean
    public A a(){
        return new A();
    }

    @Bean
    public B b(){
        return new B();
    }
}

再来看一下Spring源码中创建Bean(doCreateBean方法)三部曲:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
    
    // 省略部分源码...
    
    // 第一步,实例化bean
    instanceWrapper = createBeanInstance(beanName, mbd, args);
    // 放入三级缓存
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    
    // 第二步,填充属性
    populateBean(beanName, mbd, instanceWrapper);
    
    // 第三步,初始化
    exposedObject = initializeBean(beanName, exposedObject, mbd);
    
}

这三步源码之前也都具体分析过,如果对以上三步骤不熟悉的话,可以先去看:

Spring实例化(createBeanInstance)源码解析

Spring属性填充populateBean源码分析

Spring initializeBean源码分析

2,实例化A对象,并放入第三级缓存

这里需要注意一点,我们是通过注解@Bean方式注入bean,会把注入bean的方法解析为beanDefinition的factoryMethodName属性,以实例工厂方法的方式来注入:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
    
    // 省略部分源码...
    
    if (instanceWrapper == null) {
		// 根据执行bean使用对应的策略创建新的实例,如,工厂方法,构造函数主动注入、简单初始化
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
}
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    
    // 省略部分源码...
    
    // 如果工厂方法不为空则使用工厂方法初始化策略
	if (mbd.getFactoryMethodName() != null) {
		return instantiateUsingFactoryMethod(beanName, mbd, args);
	}
}

接下来就是获取工厂实例CycleConfiguration实例,以及工厂方法a(),来通过反射调用此方法来完成A对象的创建:

public BeanWrapper instantiateUsingFactoryMethod(
			String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
    
    // 省略部分源码...
    
    // 拿到CycleConfiguration实例类以及工厂方法a(),通过反射调用工厂方法a(),生成Bean对象,并将该Bean对象保存到bw中
	bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
}

实例化A对象之后,生成FactoryObject,然后放入第三级缓存:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
    
    // 省略部分源码...
    
    // 为避免后期循环依赖,可以在bean初始化完成前将创建实例的ObjectFactory加入工厂
	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}


protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
	// 使用singletonObjects进行加锁,保证线程安全
	synchronized (this.singletonObjects) {
	// 如果单例对象的高速缓存【beam名称-bean实例】没有beanName的对象
	if (!this.singletonObjects.containsKey(beanName)) {
		// 将beanName,singletonFactory放到单例工厂的缓存【bean名称 - ObjectFactory】
		this.singletonFactories.put(beanName, singletonFactory);
		// 从早期单例对象的高速缓存【bean名称-bean实例】 移除beanName的相关缓存对象
		this.earlySingletonObjects.remove(beanName);
		// 将beanName添加已注册的单例集中
		this.registeredSingletons.add(beanName);
	}
  }
}

3,填充A对象的b属性,当前容器中没有B对象,则doCreateBean创建B对象

填充A对象的b属性:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
    
    // 省略部分源码...
    
    // 填充属性
    populateBean(beanName, mbd, instanceWrapper);
}


protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof InstantiationAwareBeanPostProcessor) {
			//将bp 强转成 InstantiationAwareBeanPostProcessor 对象
			InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
			PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					
        }
	}
}

通过beanPostProcessor的AutowiredAnnotationBeanPostProcessor类来完成对@Autowired属性赋值操作:

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
		implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
    @Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		// 从缓存中取出这个bean对应的依赖注入的元信息~
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
			// 进行属性注入
			metadata.inject(bean, beanName, pvs);
		}
		return pvs;
	}
}

遍历前面注册的InjectedElement,然后进行注入:

public class InjectionMetadata {
    public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
		Collection<InjectedElement> checkedElements = this.checkedElements;
		Collection<InjectedElement> elementsToIterate =
				(checkedElements != null ? checkedElements : this.injectedElements);
		if (!elementsToIterate.isEmpty()) {
			for (InjectedElement element : elementsToIterate) {
				if (logger.isTraceEnabled()) {
					logger.trace("Processing injected element of bean '" + beanName + "': " + element);
				}
				element.inject(target, beanName, pvs);
			}
		}
	}
}

接下来需要从容器中获取B对象,来完成对A对象的b属性赋值:

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
		implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
    // 从容器中获取B对象
    alue = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    
    if (value != null) {
		// 通过反射,给属性赋值
		ReflectionUtils.makeAccessible(field);
		field.set(bean, value);
	}
}

DefaultListableBeanFactory#resolveDependency()—>DefaultListableBeanFactory#doResolveDependency()—>DependencyDescriptor#resolveCandidate()—>beanFactory.getBean(beanName)—>doGetBean()—>createBean()—>doCreateBean()

好了,通过一大圈的方法调用,结果又回调到了doCreateBean方法,但是此时doCreateBean是创建B对象的:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
    
    // 省略部分源码...
    
    // 第一步,实例化bean
    instanceWrapper = createBeanInstance(beanName, mbd, args);
    // 放入三级缓存
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    
    // 第二步,填充属性
    populateBean(beanName, mbd, instanceWrapper);
    
    // 第三步,初始化
    exposedObject = initializeBean(beanName, exposedObject, mbd);
    
}

4,实例化B对象,加入三级缓存,填充B对象的a属性:

上面createBeanInstance()和addSingletonFactory()方法流程我们已经看过了,这里直接省略了,上面两个方法主要完成B对象的实例化和把实例化后的B对象加入三级缓存。

接下来我们重点看一下填充B对象的a属性里面对A对象查找:

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// Quick check for existing instance without full singleton lock
		// 从单例对象缓存中获取beanName对应的单例对象
		Object singletonObject = this.singletonObjects.get(beanName);
		// 如果单例对象缓存中没有,并且该beanName对应的单例bean正在创建中
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			//从早期单例对象缓存中获取单例对象(之所称成为早期单例对象,是因为earlySingletonObjects里
			// 的对象的都是通过提前曝光的ObjectFactory创建出来的,还未进行属性填充等操作)
			singletonObject = this.earlySingletonObjects.get(beanName);
			// 如果在早期单例对象缓存中也没有,并且允许创建早期单例对象引用
			if (singletonObject == null && allowEarlyReference) {
				// 如果为空,则锁定全局变量并进行处理
				synchronized (this.singletonObjects) {
					// Consistent creation of early reference within full singleton lock
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						singletonObject = this.earlySingletonObjects.get(beanName);
						if (singletonObject == null) {
							// 当某些方法需要提前初始化的时候则会调用addSingletonFactory方法将对应的ObjectFactory初始化策略存储在singletonFactories
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							if (singletonFactory != null) {
								// 如果存在单例对象工厂,则通过工厂创建一个单例对象
								singletonObject = singletonFactory.getObject();
								// 记录在缓存中,二级缓存和三级缓存的对象不能同时存在
								this.earlySingletonObjects.put(beanName, singletonObject);
								// 从三级缓存中移除
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;
	}
}

从三级缓存中的FactoryObject的表达式中获取真实的A对象

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		// 默认最终公开的对象是bean
		Object exposedObject = bean;
		// mbd的systhetic属性:设置此bean定义是否是"synthetic",一般是指只有AOP相关的pointCut配置或者Advice配置才会将 synthetic设置为true
		// 如果mdb不是synthetic且此工厂拥有InstantiationAwareBeanPostProcessor
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			// 遍历工厂内的所有后处理器
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				// 如果bp是SmartInstantiationAwareBeanPostProcessor实例
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					// 让exposedObject经过每个SmartInstantiationAwareBeanPostProcessor的包装
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
				}
			}
		}
		// 返回最终经过层次包装后的对象
		return exposedObject;
	}

以上代码主要完成从三级缓存中获取A对象,然后加入把A对象从三级缓存中清除,加入到二级缓存中,并把此A对象返回,注意:此时A对象依然是不完整的对象,只完成了实例化,并未完成初始化。

此时拿到A对象之后用反射给B对象的a属性完成赋值操作。

5,B对象完成创建,并把B对象加入到一级缓存中,然后把完整的B对象返回,赋值给A对象的b属性

B对象完成创建,从三级缓存中移除不完整的B对象,并把完整的B对象加入到一级缓存中:

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        // 生成了新的单例对象
		if (newSingleton) {
		// 将beanName和singletonObject的映射关系添加到该工厂的单例缓存中:
			addSingleton(beanName, singletonObject);
		}
    }
}

protected void addSingleton(String beanName, Object singletonObject) {
	synchronized (this.singletonObjects) {
		// 将映射关系添加到单例对象的高速缓存中
		this.singletonObjects.put(beanName, singletonObject);
		// 移除beanName在单例工厂缓存中的数据
		this.singletonFactories.remove(beanName);
		// 移除beanName在早期单例对象的高速缓存的数据
		this.earlySingletonObjects.remove(beanName);
		// 将beanName添加到已注册的单例集中
		this.registeredSingletons.add(beanName);
	}
}

然后把完整的B对象返回,赋值给A对象的b属性。

6,A对象完成创建,并且把二级缓存中的A对象移除,把完整A对象添加到一级缓存中

源码如上addSingleton()方法。

三,二级缓存能不能解决循环依赖问题?

这里先给出答案:二级缓存可以解决循环依赖问题

我们只需要修改源码:

1,不再去三级缓存中获取。

2,不再向三级缓存中添加。

1,修改DefaultSingletonBeanRegistry类,不再去三级缓存中获取,改为从二级缓存中获取

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
   /**
    * 源代码1
    */
   // private final Map singletonObjects = new ConcurrentHashMap<>(256);
   // private final Map> singletonFactories = new HashMap<>(16);
   // private final Set registeredSingletons = new LinkedHashSet<>(256);
    /**
     * 修改后的代码1 把private给成public
     */
    public final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    public final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
    public final Set<String> registeredSingletons = new LinkedHashSet<>(256);
    
    /**
     * 源代码2
     */
    //	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//		// Quick check for existing instance without full singleton lock
//		// 从单例对象缓存中获取beanName对应的单例对象
//		Object singletonObject = this.singletonObjects.get(beanName);
//		// 如果单例对象缓存中没有,并且该beanName对应的单例bean正在创建中
//		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//			//从早期单例对象缓存中获取单例对象(之所称成为早期单例对象,是因为earlySingletonObjects里
//			// 的对象的都是通过提前曝光的ObjectFactory创建出来的,还未进行属性填充等操作)
//			singletonObject = this.earlySingletonObjects.get(beanName);
//			// 如果在早期单例对象缓存中也没有,并且允许创建早期单例对象引用
//			if (singletonObject == null && allowEarlyReference) {
//				// 如果为空,则锁定全局变量并进行处理
//				synchronized (this.singletonObjects) {
//					// Consistent creation of early reference within full singleton lock
//					singletonObject = this.singletonObjects.get(beanName);
//					if (singletonObject == null) {
//						singletonObject = this.earlySingletonObjects.get(beanName);
//						if (singletonObject == null) {
//							// 当某些方法需要提前初始化的时候则会调用addSingletonFactory方法将对应的ObjectFactory初始化策略存储在singletonFactories
//							ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
//							if (singletonFactory != null) {
//								// 如果存在单例对象工厂,则通过工厂创建一个单例对象
//								singletonObject = singletonFactory.getObject();
//								// 记录在缓存中,二级缓存和三级缓存的对象不能同时存在
//								this.earlySingletonObjects.put(beanName, singletonObject);
//								// 从三级缓存中移除
//								this.singletonFactories.remove(beanName);
//							}
//						}
//					}
//				}
//			}
//		}
//		return singletonObject;
//	}
    
    /**
     * 修改后的代码2
     */
    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);
					return singletonObject;
				}
			}
		return singletonObject != null ? singletonObject:null;
	}
    
}

2,AbstractAutowireCapableBeanFactory类的doCreateBean()方法,不再去向三级缓存中添加,改为向二级缓存中添加

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
		implements AutowireCapableBeanFactory {
    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
        /**
         * 修改源代码,不再去向三级缓存中添加
         */
//		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

		/**
		 * 改为只向二级缓存中添加
		 */
		earlySingletonObjects.put(beanName,bean);
		registeredSingletons.add(beanName);
    }
}

以上改源码完成之后运行我们的例子,发现依然可以运行成功!

四,既然二级缓存可以解决循环依赖,为什么还要加入三级缓存?

我们再上面的例子上面加入aop,然后再运行,当调试到B对象给a属性赋值时,会去三级缓存中获取FactoryObject然后调用getEarlyBeanReference()方法:

	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		// 默认最终公开的对象是bean
		Object exposedObject = bean;
		// mbd的systhetic属性:设置此bean定义是否是"synthetic",一般是指只有AOP相关的pointCut配置或者Advice配置才会将 synthetic设置为true
		// 如果mdb不是synthetic且此工厂拥有InstantiationAwareBeanPostProcessor
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			// 遍历工厂内的所有后处理器
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				// 如果bp是SmartInstantiationAwareBeanPostProcessor实例
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					// 让exposedObject经过每个SmartInstantiationAwareBeanPostProcessor的包装
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
				}
			}
		}
		// 返回最终经过层次包装后的对象
		return exposedObject;
	}

我们加入了Aop的话,会有一个AbstractAutoProxyCreator的SmartInstantiationAwareBeanPostProcessor后置处理器来完成B实例的代理对象生成:

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    
    @Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			// 根据给定bean的name和class构建出一个key
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				// 如果它需要被代理,则需要封装指定的bean
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}
    
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// 如果已经处理过,直接返回
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		// 如果不需要增强,则直接返回
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		// 判断给定的bean类是否代表一个基础设施类,基础设施类不应代理,或者配置了指定bean不需要自动代理
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		// 如果存在增强方法则创建代理
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		// 如果获取到了增强则需要针对增强创建代理
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			// 创建代理
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}
}

返回A的代理对象给B类的a属性赋值。

重点:

如果这里不加三级缓存,而是只有二级缓存的话,那么你给B对象赋值a属性的A对象是一个普通的A对象,而当你在完成A对象的实例化时,在initializeBean()方法中会给A生成代理对象,所以会导致实际放入容器的是A的代理对象,而给B赋值的是A的普通对象(也就是通过new产生的),所以这里为了解决Aop代理的时候,对象一致而加入了三级缓存。

一句话总结就是:如果不加三级缓存,那么在使用Aop的时候会导致爆漏出去的对象和实际产生的对象不一致。

你可能感兴趣的:(吃透Spring源码,Spring循环依赖源码,二级缓存实现循环依赖,为什么用三级缓存实现循环依赖)