跳至主要內容

13、Spring循环依赖源码分析

安图新大约 13 分钟

13、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)源码解析open in new window

Spring 属性填充 populateBean 源码分析open in new window

Spring initializeBean 源码分析open in new window

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<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
   // private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
   // private final Set<String> 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 的时候会导致爆漏出去的对象和实际产生的对象不一致。

上次编辑于:
贡献者: Andy