解决spring的循环依赖的源码解析

1.什么是循环依赖
在这里插入图片描述

2.什么是三级缓存

  1. 一级缓存 : 单列池 singletonObjects 存放的bean生命周期的对象
  2. 二级缓存 : earlySingletonObjects 存放由原始对象进行aop后的对象(存在循环依赖才会放入到这个集合中的对象)
  3. 三级缓存 : singletonFactories 存放生命周期中的原始对象(生命周期中没有被aop代理的对象,它的键名是service的名字,值是一个lambda表达式,lambda表达式在存入map的时候是不会被执行的)

3.源码缓存的集合

/** Cache of singleton objects: bean name to bean instance. */
//单列池
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name to ObjectFactory. */
//三级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name to bean instance. */
//二级缓存
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

/** Set of registered singletons, containing the bean names in registration order. */
private final Set registeredSingletons = new LinkedHashSet<>(256);

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {

	// Quick check for existing instance without full singleton lock
//直接在缓存单列池里面查询
	Object singletonObject = this.singletonObjects.get(beanName);
// 如果单列池中为空,并且是正在创建的状态
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
 //	在更在的缓存集合中进行查找
		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) {
        	//三级缓存中查到的 函数表达式 ObjectFactory 是一个函数表达式接口
						ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
						if (singletonFactory != null) {
          //	aop代理 代理三级缓存中的原始对象 
							singletonObject = singletonFactory.getObject();
            //	存放到二级缓存里
							this.earlySingletonObjects.put(beanName, singletonObject);
            //把三级缓存中存在的对象删除
							this.singletonFactories.remove(beanName);
						}
					}
				}
			}
		}
	}
	return singletonObject;
}

为什么单列池用的ConcurrentHashMap而三级缓存和二级缓存不用ConcurrentHashMap,因为ConcurrentHashMap 在put和remove的时候都需要进行加锁。每个操作都是一把锁。这里代码直接用synchronized 直接进行代码块上锁,保证了代码的原子性。
4.简单生命周期示意图
在这里插入图片描述

5.如何判断一个类是不是提前进行了aop
在这里插入图片描述

最终是是实现了BeanPostProcessor 定层接口实现生命周期。AbstractAutoProxyCreator只是为了实现aop,如果不需要实现aop则不需要这个类,同时也是这个类来判断是不是提前进行了aop。

首先找到二级缓存存放的map。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
//循环所有的是 SmartInstantiationAwareBeanPostProcessor 类型的 BeanPostProcessorCache 后置处理器
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}

public Object getEarlyBeanReference(Object bean, String beanName) {
// cacheKey 实际上就是beanName
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
// 将原始对象和beanName放入earlyProxyReferences 集合中
// earlyProxyReferences 是三级缓存之外的一个缓存集合,就是将来用来判断的map
// 在初始化属性的时候,值为 private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap(16);
this.earlyProxyReferences.put(cacheKey, bean);
return this.wrapIfNecessary(bean, beanName, cacheKey);
}

//所有bean的生命周期的最后一步
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
//判断集合中移除的对象是否是当前方法传递的参数 bean 原始对象。
//如果不是原始对象,那么就使用wrapIfNecessary 进行产生aop代理对象
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
//这里解决了第二个问题,如何保证不会再次进行生成aop对象的操作
return bean;
}

6.循环依赖中生成的aop对象是什么时候放入单列池的
在这里插入图片描述

截图中的意思是,当前对象是原始对象Aservice 但是Bservice中的aService属性已经是一个aop代理对象了

if (earlySingletonExposure) {
// getSingleton 此方法是重新调用的从单列池、二级缓存、三级缓存中查找到对象
// 1,因为aService 没有放入单列池中,所以在第一级中无法找到,但是在完成了aop代理对象的生成
// 所以在二级对象中能找到。
// 所以 earlySingletonReference 是一个aop代理对象并且不为空
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
//如果传入的对象等于原始对象,那么直接把aop对象向原始对象赋值
// 为什么这里要进行判断,因为BeanPostProcessor不只一个,我们可以实现接口自定义。aop的 BeanPostProcessor
//只是其中的一种
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
//如果提前暴露的对象和经过了完整的生命周期后的对象不相等
// allowRawInjectionDespiteWrapping表示在循环依赖时,只能
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
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.”);
}
}
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值