Spring IOC 源码学习 环境准备

什么是循环依赖?

当一个Bean依赖于另一个Bean时,这个被依赖的Bean同样也依赖于第一个Bean,从而形成一个循环链。这种循环关系可能会导致初始化和依赖注入的问题,因为它们都依赖于同一个目标实例

比如: “A对象依赖B对象, 而B对象也依赖A对象” AB BA

此时,图中是一个闭环,如果想解决这个问题,那么就必须要保证不会出现第二次创建A对象这个步骤,也就是说从容器中获取A的时候必须要能够获取到

解决循环依赖? 提前暴露

实例化好单未完成初始化的对象是可以直接给其他对象引用的,所以此时可以做一件事,把完成实例化但未完成初始化的对象提前暴露出去,让其他对象能够进行引用,就完成了这个闭环的解环操作;

这也就是常规说的提前暴露对象

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
......
		/**
		 * 判断当前:  是否单例 && 是否允许循环依赖 && 是否正在创建过程中
		 */
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			/**
			 * 不管需不需要, 先放到三级缓存, 提前暴露出去
			 */
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}
 
......
 
}

为什么需要三级缓存?

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry

/** Cache of singleton objects: bean name to bean instance. */  
/**  
 * 一级缓存  这是最终缓存实例的地方,保存完全初始化并准备好的Bean实例。
 * 所属: org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#singletonObjects
 */  
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);  
  
/** Cache of singleton factories: bean name to ObjectFactory. */  
/**  
 * 三级缓存   
 * 里面存放的是将要被实例化的对象的对象工厂(存放 bean 工厂对象),是一个包裹对象`ObjectFactory(registeredSingletons)`,经过getObject获取到早期对象。 
 * 所属: org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#singletonFactories
 */  
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);  
  
/** Cache of early singleton objects: bean name to bean instance. */  
/**  
 * 二级缓存  
 * 存放早期暴露出来的Bean对象,实例化以后,就把对象放到这个Map中。(Bean可能只经过实例化,属性还未填充)
 * 所属: org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#earlySingletonObjects
 */  
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

第一级缓存: org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#singletonObjects 里面放置的是已经实例化 完整可用的 单例缓存池(singletonObjects)

第二级缓存: org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#earlySingletonObjects 里面存放的是提早曝光的单例对象,早期对象(earlySingletonObjects)。简单粗暴的说就是new的对象, 可是这个对象还没填充属性, 全部属性都是null

第三级缓存: org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#singletonFactories 里面存放的是将要被实例化的对象的对象工厂(存放 bean 工厂对象),是一个包裹对象ObjectFactory(registeredSingletons),经过getObject获取到早期对象。

不是为解决循环依赖

正常来讲, 处理循环依赖, 类似交换变量 (temp约等于缓存), 只需要一级缓存即可;

function swap(a, b){
	temp = a;
	a = b;
	b = temp;
}

加上单例缓存池, 只需两级缓存

增加的第三级缓存

第三级缓存是处理 AOP 增强bean 的问题;

类似上面的例子, 解决 实例A 和 代理A , 保证只有一个能用的A对象

因为不知道 当前对象什么时候会被引用,是否需要被代理, 所以先把它 (bean 名称, bean实例 和 bean BeanDefinition 参数) 预变成一个lambda表达式 放在三级缓存中, 它有可能会被处理成AOP代理 对象 (在被引用的时候来判断对象是否需要被代理, 决定是否织入AOP)

例入: Aservice 依赖 Bservice 并且Bservice 依赖Aservice

  1. 创建Aservice时,实例化后, 将生成A的lambda放入三级缓存, 填充属性 Bservice,一二三级缓存中都没找到,
  2. 去创建Bservice,实例化后, 将生成B的lambda放入三级缓存, 填充Aservice属性,发现三级缓存中有A,执行A的lambda生成Aservice对象 (如果A需要被代理, 将在这里处理, 即: 不知道A是否需要动态代理, 在第一次引用的时候进行判断, 并处理它),并将A放入二级缓存(不能放一级这时候A的全部属性还是null),并删除A的三级缓存
  3. 继续执行B的 lambda 生成Bservice对象 (如果B也需要被代理, 将在这里处理) 将B放入一级缓存,并删除B的三级缓存; 此时: Bservice已完整可用, 且其AService属性是代理后的对象;
  4. 继续创建A的流程, 填充属性 初始化, 再从缓存中拿一次获取并替换(因为有可能A被代理了, 两次地址不一致就是被代理了, 参考下源码)
  5. 最后再将A (或者代理A)放入一级缓存中 代理A的对象属性是null, 它不需要, 持有原始对象A就行了

增强代理的相关源码

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
 
		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			/**
			 *  1. 实例化
			 */
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}
 
		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					/**
					 * 处理 MergedBeanDefinitionPostProcessor 的接口回调
					 */
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.markAsPostProcessed();
			}
		}
 
		/**
		 * 判断当前:  是否单例 && 是否允许循环依赖 && 是否正在创建过程中
		 *(循环依赖AOP) <!>
		 */
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			/**
			 * 携带beanName,mbd 和原始bean示例 创建为 Lambda 表达式
			 * 
			 * 放到三级缓存中
			 * 
			 * <!> 循环依赖 AOP :这里其实还是会调用到 AutoProxyCreator 在其进行判断是否需要代理, 最终会调用到 createProxy 进行动态代理对象创建
			 * {@link org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getEarlyBeanReference(java.lang.Object, java.lang.String)}
			 */
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}
 
		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			/**
			 * 2.填充Bean属性
			*   如果是AOP, pointcut, advice相关的会   调用 BeanPostProcessor 的子接口 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation  
			*   (作用是 在实例化之后,属性填充之前执行操作, 可以拦截属性填充操作)
			 */
			populateBean(beanName, mbd, instanceWrapper);
			/**
			 * 3.初始化Bean对象
			 */
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException bce && beanName.equals(bce.getBeanName())) {
				throw bce;
			}
			else {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex);
			}
		}
 
		if (earlySingletonExposure) {
			/**
			 * (循环依赖AOP) 相关 
			 * =======================
			 */
 
			/**
			 * 再从缓存中 再次获取并替换,是因为有可能是被代理
			 */
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				/**
				 *  (循环依赖AOP) <!>
				 *  注意: 这个bean是原始实例, 再从缓存中拿一次,是因为有可能是被代理(earlySingletonReference)
				 */
				if (exposedObject == bean) {
					// 不一致就是被代理了
					exposedObject = earlySingletonReference;
				}
				
......