Spring源码分析二:单例bean的获取 - createBean

一、前言

本文是笔者阅读Spring源码的记录文章,由于本人技术水平有限,在文章中难免出现错误,如有发现,感谢各位指正。在阅读过程中也创建了一些衍生文章,衍生文章的意义是因为自己在看源码的过程中,部分知识点并不了解或者对某些知识点产生了兴趣,所以为了更好的阅读源码,所以开设了衍生篇的文章来更好的对这些知识点进行进一步的学习。

本文衍生篇:

  1. Spring 源码分析衍生篇三 : lookup-method 和 replaced-method
  2. Spring 源码分析衍生篇四 : 后处理器 BeanPostProcesser

一、前情提要

这篇文章应该是接着 Spring 源码分析一 :bean的加载过程 的继续分析过程。
本文主要是分析Spring 如何创建 单例bean的过程。

Spring 源码分析一 :bean的加载过程 的分析过程中,我们分析了bean的加载过程,最后经过重重判断,终于到了
DefaultSingletonBeanRegistry#getSingleton(java.lang.String, ObjectFactory<?>)这一步(如下图)。
在这里插入图片描述
到了这一步,Spring 就基本对 Bean已经创建好了不抱什么希望了,所以着手开始创建bean。
本文就来分析 getSingleton(String beanName, ObjectFactory<?> singletonFactory) 方法整个流程。

二、获取单例 - getSingleton

如下, 是整个 getSingleton方法的代码,做了一些基本注释

	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    
    
		Assert.notNull(beanName, "Bean name must not be null");
		// singletonObjects全局变量需要加锁
		synchronized (this.singletonObjects) {
    
    
			// 1. 再次尝试获取bean,判断bean是否已经加载。如果加载直接返回。
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
    
    
				// 2. 判断,如果当前beanFactory正在被销毁则直接抛出异常,不允许创建单例bean
				if (this.singletonsCurrentlyInDestruction) {
    
    
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
    
    
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				// 3. 做一些bean创建前的准备工作: 记录beanName 正在加载的状态,若bean已经正在加载,则抛出异常。为了解决循环引用的问题
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
    
    
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
    
    
					// 4. 通过回调方式获取bean实例。
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
    
    
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
    
    
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
    
    
					if (recordSuppressedExceptions) {
    
    
						for (Exception suppressedException : this.suppressedExceptions) {
    
    
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
    
    
					if (recordSuppressedExceptions) {
    
    
						this.suppressedExceptions = null;
					}
					// 5. 加载单例后的处理方法调用 : 删除bean正在创建的记录
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
    
    
					// 6. 加入到缓存中,并删除加载bean过程中所记录的各种辅助状态
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

	...
	// 主要还是对几个缓存map的操作
	protected void addSingleton(String beanName, Object singletonObject) {
    
    
		synchronized (this.singletonObjects) {
    
    
			this.singletonObjects.put(beanName, singletonObject);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}
	...
	
		protected void beforeSingletonCreation(String beanName) {
    
    
			if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
    
    
				throw new BeanCurrentlyInCreationException(beanName);
			}
		}
	...
		protected void afterSingletonCreation(String beanName) {
    
    
			if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
    
    
				throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
			}
		}


上面的代码注释也比较清楚,基本流程如下:

  1. this.singletonObjects.get(beanName); :再次尝试从缓存中获取bean,若获取到,则直接返回。
  2. if (this.singletonsCurrentlyInDestruction) :未获取到检测bena是否正在销毁,若是则抛出异常
  3. beforeSingletonCreation 方法中记录bean正在创建的状态将beanName添加到singletonsCurrentlyInCreation集合中)。在循环依赖时可根据此判断。
  4. singletonObject = singletonFactory.getObject(); :调用 ObjectFactory.getObject() 方法来实例化bean
  5. afterSingletonCreation 方法移除bean正在夹杂的状态
  6. addSingleton(beanName, singletonObject); : 对各种缓存状态做处理。

流程图如下所示 :
在这里插入图片描述
可以非常直观的看出, getSingleton 方法中的关键逻辑非常简单,bean创建的具体逻辑在 singletonObject = singletonFactory.getObject(); 中,所以下面继续去分析singletonFactory.getObject()中做了什么。


三、创建bean - createBean

上面可以看到,主要步骤还是在回调的 getObject() 方法中。那么我们来看看在bean加载过程中的FactoryBean做了什么。代码如下:
在这里插入图片描述

兜了一大圈关键代码还是在createBean 方法里。接下来,我们就来仔细分析一下 createBean 方法。


AbstractAutowireCapableBeanFactory#createBean 方法代码如下 ,附带部分注释:

	/**
	 * Central method of this class: creates a bean instance,
	 * populates the bean instance, applies post-processors, etc.
	 * @see #doCreateBean
	 */
	@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
    
    

		if (logger.isTraceEnabled()) {
    
    
			logger.trace("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
		// 1. 锁定class, 根据设置的class属性或者根据className来解析class
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    
    
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
		try {
    
    
			// 2. 验证及准备覆盖的方法
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
    
    
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
    
    
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			// 3. 调用BeanProcessors的方法来替代真正的实例
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			// 如果后处理器真的实现了,则直接返回使用后处理器的bean
			if (bean != null) {
    
    
				return bean;
			}
		}
		catch (Throwable ex) {
    
    
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
    
    
			// 4.  创建bean 的 真正方法
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
    
    
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
    
    
			// A previously detected exception with proper bean creation context already,
			// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
			throw ex;
		}
		catch (Throwable ex) {
    
    
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}

可以看到,createBean 的整体流程大致如下:

  1. 根据设置的class属性或者根据className来解析Class。
  2. 对override 属性进行标记及验证。
  3. 应用初始化前的后处理器,解析指定bean是否存在初始化前的短路操作。
  4. 创建bean。
  5. 返回bean

流程图如下:
在这里插入图片描述

看着似乎不复杂,实际上,真正的逻辑都被封装在了方法中,所以下面需要关注如下的几个方法:

1、resolveBeanClass

这里不再过多展示代码,这个方法的作用就是根据参数和返回值都能知道: 根据 BeanDefinition和 beanName 解析出 bean 的Class。

		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);

2、prepareMethodOverrides

见名知意: 准备方法重写。这个方法主要是针对 lookup-methodreplaced-method 两个属性的,用来覆盖指定的方法。

	mbdToUse.prepareMethodOverrides();

详细代码如下:

	public void prepareMethodOverrides() throws BeanDefinitionValidationException {
    
    
		// Check that lookup methods exist and determine their overloaded status.
		// 判断是否有方法需要重写
		if (hasMethodOverrides()) {
    
    
			getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
		}
	}

	protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
    
    
		// 获取对应的类中的对应方法名的个数
		int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
		// 等于0抛出异常
		if (count == 0) {
    
    
			throw new BeanDefinitionValidationException(
					"Invalid method override: no method with name '" + mo.getMethodName() +
					"' on class [" + getBeanClassName() + "]");
		}
		else if (count == 1) {
    
    
			// Mark override as not overloaded, to avoid the overhead of arg type checking.
			// 标记 MethodOverride 暂未被覆盖,避免参数类型检查的开销。
			mo.setOverloaded(false);
		}
	}

解释一下上面的逻辑:

  1. 首先会判断是否有方法需要重写,这里的是根据 RootBeanDefinition 中的 methodOverrides 属性来进行判断,为空则表示没有。
  2. 若上述判断有方法需要覆盖,则会调用prepareMethodOverride(MethodOverride mo) 方法。而在 prepareMethodOverride(MethodOverride mo) 方法中会根据 需要覆盖的方法名称 来获取加载类中关于该方法的实现。如果获取不到 count == 0,则直接抛出异常,如果获取到只有一个 count == 1,则记录该方法并未被重载(因为Spring在方法匹配时,如果一个类中存在若干个重载方法,则在函数调用及增强的时候需要根据参数类型进行匹配,来最终确定调用的方法是哪一个,这里直接设置了该方法并未被重载,在后续方法匹配的时候就不需要进行参数匹配验证,直接调用即可)。
  3. 打个比方,比如指定覆盖A类中的 a方法,但是A类中可能存在多个a方法或者不存在a方法,若count == 0不 存在a方法,则谈何覆盖,直接抛出异常,若count ==1 则a方法的实现只有一个,标记该方法并未被重载后续可跳过参数验证的步骤。

3、resolveBeforeInstantiation

该方法主要是调用Bean后处理器来进行一些处理,代码实现上非常简单。

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

该方法调用了后处理器的方法:

  • InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation(Class<?> beanClass, String beanName) :
  • InstantiationAwareBeanPostProcessor.postProcessAfterInitialization(Object bean, String beanName) :

在调用 doCreate 方法创建bean的实例前调用了该方法对 BeanDefinition 中的属性做一些前置处理。

	@Nullable
	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    
    
		Object bean = null;
		// 如果尚未被解析
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
    
    
			// Make sure bean class is actually resolved at this point.
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    
    
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
    
    
					// 实例前的后处理器应用
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
    
    
						// 实例后的后处理器应用
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

其中 applyBeanPostProcessorsBeforeInstantiationapplyBeanPostProcessorsAfterInitialization 很明显就是调用bean的后处理器,也就是对后处理器中的 InstantiationAwareBeanPostProcessor 类型的后处理器进行 postProcessBeforeInstantiation 方法 和 BeanPostProcessor 类型的 postProcessAfterInitialization 方法的调用。

3.1 postProcessBeforeInstantiation

在bean 实例化前调用,也就是将 AbstractBeanDefinition 转换为 BeanWrapper 前的处理。给子类一个修改BeanDefinition的机会,也就是说当程序经过这个方法后,bean可能已经不是我们所认为的bean了。或许是一个经过代理的代理bean。可能是通过cglib生成的,也可能是通过其他技术生成的。
代码逻辑比较简单,这里不再介绍。

	protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    
    
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
    
    
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
    
    
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
    
    
					return result;
				}
			}
		}
		return null;
	}

3.2 postProcessAfterInitialization

这里也是一目了然。

	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {
    
    

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
    
    
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
    
    
				return result;
			}
			result = current;
		}
		return result;
	}

4、创建bean - doCreateBean

Spring do开头的方法才是真正做事情的,所以这里才是真正创建bean的地方。

	Object beanInstance = doCreateBean(beanName, mbdToUse, args);

doCreateBean 代码如下,带有详细注释:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {
    
    

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
    
    
			// 1. 如果bean是单例,需要先清除缓存
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
    
    
			// 2. 根据指定的bean使用对应的策略创建新的实例。如:工厂方法、构造函数自动注入,简单初始化
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
    
    
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		// 3. 调用  MergedBeanDefinitionPostProcessor 后处理器
		synchronized (mbd.postProcessingLock) {
    
    
			if (!mbd.postProcessed) {
    
    
				try {
    
    
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
    
    
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		// 4. 判断是否需要提早曝光 : 单例 & 允许循环依赖 & 当前bean正在创建中,检测循环依赖
		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");
			}
			// 5. 为避免后期循环依赖,在bean初始化完成前将创建实例的ObjectFactory 加入工程  -- 解决循环来
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
    
    
			//  6. 对bean进行属性填充,将各个属性值注入,其中如果存在依赖于其他bean的属性,则会递归初始依赖bean
			populateBean(beanName, mbd, instanceWrapper);
			// 调用初始化方法,比如 init-method
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
    
    
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
    
    
				throw (BeanCreationException) ex;
			}
			else {
    
    
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}
		// 7. 进行循环依赖检查
		if (earlySingletonExposure) {
    
    
			Object earlySingletonReference = getSingleton(beanName, false);
			// earlySingletonReference  只有在检测到有循环依赖的情况下才会不为空
			if (earlySingletonReference != null) {
    
    
			// 如果 exposedObject没有在初始化方法中被改变,也就是没有被增强
				if (exposedObject == bean) {
    
    
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
    
    
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
    
    
						// 检测依赖
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
    
    
							actualDependentBeans.add(dependentBean);
						}
					}
					// 因为bean创建后其所依赖的bean一定是已经创建了的。actualDependentBeans不为空说明当前 bean创建后其依赖的bena却没有全部创建完,也就说说存在循环依赖。
					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 " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
    
    
			// 8.根据Scopse 注册bean
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
    
    
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

可以看到大致逻辑如下:

  1. createBeanInstance(beanName, mbd, args) :实例化bean,将BeanDefinition转换为BeanWrapper
  2. applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); : MergedBeanDefinitionPostProcessor 后处理器的应用。bean合并后的处理,Autowired注解正式通过此方法实现诸如类型的预解析。
  3. addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); : 关于循环依赖的处理,添加 ObjectFactory到singletonFactories缓存中,同时对SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference后处理器的应用
  4. populateBean(beanName, mbd, instanceWrapper); :属性填充
  5. initializeBean(beanName, exposedObject, mbd); : 初始化bean的一些属性,如Aware 接口的实现, init-method属性等
  6. 循环依赖检查。和第四步不同的是,这里了是判断是否无法解决循环依赖,否则抛出异常。
  7. registerDisposableBeanIfNecessary(beanName, bean, mbd); : 注册DisposableBean
  8. 完成创建并返回。

doCreatebean 方法的代码量非常大,这里由于篇幅问题,需要新开篇分析,所以本文中挑选几个简单的方法分析,复杂的方法新开篇分析。

4.1 createBeanInstance

见名知意 : 该方法完成了bean的实例创建。

instanceWrapper = createBeanInstance(beanName, mbd, args);

大概逻辑可以概括为:

  1. 如果存在工厂方法则使用工厂方法进行初始化
  2. 若类有多个构造函数,则根据参数锁定构造函数并初始化
  3. 如果即不存在工厂方法也不存在带参构造函数,则使用默认的构造函数进行bean的实例化。

具体的代码分析已成文 : Spring源码分析三:bean的创建 - createBeanInstance

4.2. applyMergedBeanDefinitionPostProcessors

这种方法命名的也见得多了,见名知意: 该方法完成了 MergedBeanDefinitionPostProcessors 后处理器的功能,主要是 bean合并后的处理,Autowired 注解正是通过该方法实现诸如类型的预解析。这个方法不必特意关注,我们实际中也基本不会使用MergedBeanDefinitionPostProcessors

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

详细代码如下,不再具体分析

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
    
    
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
    
    
			if (bp instanceof MergedBeanDefinitionPostProcessor) {
    
    
				MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
				bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
			}
		}
	}

4.3 addSingletonFactory

我们实际的分析是一部分代码块如下:

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");
			}
			// 这里为了避免后期的循环依赖,在bean初始化前将创建实例的ObjectFactory加入工厂中。
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

首先我们需要分析出 earlySingletonExposure 为true的条件:

  • bean是单例
  • 允许循环依赖
  • 当前bean正在创建中 : singletonsCurrentlyInCreation 包含当前bean。在Spring 中 有专门的属性记录 bean的加载状态 – DefaultSingletonBeanRegistry#singletonsCurrentlyInCreation。在bean创建前会将bean添加,bean创建结束后将bean移除。

满足上述三个条件后,则会 调用 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 方法。这个方法作用是将正在创建的bean缓存起来,主要目的还是用来解决循环依赖的问题。这里的作用如果需要理解,需要理解循环依赖相关: Spring 源码分析衍生篇二 : Spring中的循环依赖

	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");
			}
			// 这里为了避免后期的循环依赖,在bean初始化前将创建实例的ObjectFactory加入工厂中。
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}
		
	...
	
	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    
    
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
    
    
			if (!this.singletonObjects.containsKey(beanName)) {
    
    
				this.singletonFactories.put(beanName, singletonFactory);
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}
	
	...
	// 对 bean再一次依赖于引用,主要就是调用了SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference 方法
	// Aop 就是在这里将 Advice 动态织入bean中,若没有bean则直接返回bean,不做任何处理
	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    
    
		Object exposedObject = bean;
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    
    
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
    
    
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
    
    
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
				}
			}
		}
		return exposedObject;
	}

该方法中 getEarlyBeanReference 调用了后处理器的方法:

  • SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference (Object bean, String beanName);

4.4 populateBean

见名知意,下面这个方法是用来属性注入的。
上面的 createBeanInstance 方法创建了 bean,populateBean 方法则是对bean 属性的注入。

		populateBean(beanName, mbd, instanceWrapper);

在这里方法里按照如下顺序调用了后处理器

  • InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation :
  • InstantiationAwareBeanPostProcessor.postProcessProperties :
  • InstantiationAwareBeanPostProcessor.postProcessPropertyValues : 已过时

下面我们来详细看看代码逻辑。

	protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    
    
		if (bw == null) {
    
    
			// 没有属性抛出异常
			if (mbd.hasPropertyValues()) {
    
    
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
			}
			else {
    
    
				// Skip property population phase for null instance.
				return;
			}
		}

		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		// 这里调用了 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation方法
		// 给InstantiationAwareBeanPostProcessor最后一次机会在属性设置前来改变bean
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    
    
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
    
    
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
    
    
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;						
					// 返回值为是否继续填充bean
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    
    
						return;
					}
				}
			}
		}

		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		// 根据名称或类型自动注入
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    
    
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
    
    
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    
    
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}
		// 后处理器已经初始化
		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		// 需要依赖检查
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) {
    
    
			if (pvs == null) {
    
    
				pvs = mbd.getPropertyValues();
			}
			// 调用了InstantiationAwareBeanPostProcessor.postProcessProperties 方法 和 postProcessPropertyValues 方法 来进行设值后处理
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
    
    
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
    
    
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
    
    
						if (filteredPds == null) {
    
    
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
    
    
							return;
						}
					}
					pvs = pvsToUse;
				}
			}
		}
		// 如果需要检查
		if (needsDepCheck) {
    
    
			if (filteredPds == null) {
    
    
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			// 依赖检查,对应 depends-on 属性,3.0 已弃用
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

		if (pvs != null) {
    
    
			// 将属性应用到bean中
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

从上看下来,整个流程如下:

  1. InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 方法,可以决定程序是否继续进行属性填充。只要有一个 InstantiationAwareBeanPostProcessor 返回false,都会终止属性填充的过程。
  2. 根据注入类型(name或type),提取依赖的bean,并统一存入到 propertyValues 中。
  3. 应用 InstantiationAwareBeanPostProcessor.postProcessProperties 和 InstantiationAwareBeanPostProcessor.postProcessPropertyValues 方法,对属性获取完毕填充前对属性的再次处理。
  4. 将所有 propertyValues 中的属性填充至 BeanWrapper 中。

这里只介绍了基本逻辑,详细的代码分析 :Spring源码分析四:bean的属性注入 - populateBean

4.5 initializeBean

该方法初始化bean的一些属性,如Aware 接口的实现, init-method、InitializingBean属性等
详细代码如下

	protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    
    
		if (System.getSecurityManager() != null) {
    
    
			// 激活 Aware  接口
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    
    
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
    
    
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
    
    
			// 调用BeanPostProcessor.postProcessBeforeInitialization 方法
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
    
    
			// 激活 自定义的初始化方法方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
    
    
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
    
    
			// 调用 BeanPostProcessor.postProcessAfterInitialization 方法
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

代码比较简单,这里不再过多赘述,详细请看 : Spring源码分析五:bean的初始化 - initializeBean

4.6 循环依赖检查

Spring 循环依赖的解决仅对单例且非构造函数构造的形式有效,对于原型模式的bean,Spring直接抛出异常,在这个步骤中会检测已经加载的bean 是否已经出现了循环依赖,并判断是否需要抛出异常。

if (earlySingletonExposure) {
    
    
			// 1. 调用了 getSingleton 方法,注意并不是本文分析的getSingleton 方法,是其重载方法
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
    
    
				if (exposedObject == bean) {
    
    
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
    
    
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> 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 " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

...

	@Nullable
	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);
				if (singletonObject == null && allowEarlyReference) {
    
    
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
    
    
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

具体逻辑开新篇讲解。

4.7 . registerDisposableBeanIfNecessary

这一步的目的是实现 destory-method 属性,如果bean配置了该属性,则需要注册以便在销毁时调用。

详细代码如下:

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
    
    
		AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
		if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
    
    
			if (mbd.isSingleton()) {
    
    
				// Register a DisposableBean implementation that performs all destruction
				// work for the given bean: DestructionAwareBeanPostProcessors,
				// DisposableBean interface, custom destroy method.
				// 单例模式下注册需要销毁的bean,此方法会处理实现DisposableBean的bean
				// 并且对所有的bean使用 DestructionAwareBeanPostProcessor 处理 DisposableBean DestructionAwareBeanPostProcessor
				registerDisposableBean(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			}
			else {
    
    
				// A bean with a custom scope...
				// 自定义 scope 的处理
				Scope scope = this.scopes.get(mbd.getScope());
				if (scope == null) {
    
    
					throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
				}
				scope.registerDestructionCallback(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			}
		}
	}

五、最后

本文仍有大量内容碍于篇幅内容无法完全写出,成文后第一时间更新。


2020.5.30 : 文章已全部更新


以上:内容部分参考
《Spring源码深度解析》
如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正

猜你喜欢

转载自blog.csdn.net/qq_36882793/article/details/105800112