13、Spring循环依赖源码分析
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)源码解析
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 的时候会导致爆漏出去的对象和实际产生的对象不一致。