当前位置 : 主页 > 编程语言 > 其它开发 >

Spring Ioc源码分析系列--Bean实例化过程(二)

来源:互联网 收集:自由互联 发布时间:2022-06-01
Spring Ioc源码分析系列--Bean实例化过程(二)前言 上篇文章Spring Ioc源码分析系列--Bean实例化过程(一)简单分析了 getBean() 方法,还记得分析了什么吗?不记得了才是正常的,记住了才是怪人
Spring Ioc源码分析系列--Bean实例化过程(二) 前言

上篇文章Spring Ioc源码分析系列--Bean实例化过程(一)简单分析了getBean()方法,还记得分析了什么吗?不记得了才是正常的,记住了才是怪人,忘记了可以回去翻翻,翻不翻都没事, 反正最后都会忘了。

这篇文章是给上篇填坑的,上篇分析到真正创建Bean的createBean(beanName, mbd, args)就没有继续深入去分析了,绕得太深,说不清楚。那么这一篇,就续上这个口子,去分析createBean(beanName, mbd, args)方法。

源码分析

话不多说,我们直接来到createBean(beanName, mbd, args)方法的源码。具体的实现是在AbstractAutowireCapableBeanFactory#createBean(beanName, mbd, args)里,可以直接定位到这里。

createBean()方法

跟进代码查看,这个方法也比较简单,主要分为了以下几点:

  • 初始化化Class对象。调用resolveBeanClass(mbd, beanName)方法获取class对象,这里会去解析类全限定名,最终是通过反射方法Class<?> resolvedClass = ClassUtils.forName(className, classLoader)获取Class对象。
  • 检查覆盖方法。对应的是mbdToUse.prepareMethodOverrides()方法,这里会对一些重载方法进行标记预处理,如果同方法名的方法只存在一个,那么会将覆盖标记为未重载,以避免 arg 类型检查的开销。
  • 应用后置处理器。在实例化对象前,会经过后置处理器处理,这个后置处理器的提供了一个短路机制,就是可以提前结束整个Bean的生命周期,直接从这里返回一个Bean。
  • 创建Bean。调用doCreateBean()方法进行Bean的创建,在Spring里面,带有do开头的一般是真正干活的方法,所以Ioc创建Bean到这里,才是真正要到干活的地方了。

我们庖丁解牛先把方法不同的功能按照逻辑拆分了,那接下来,就详细分析一下每个部分。

	/**
	 * Central method of this class: creates a bean instance,
	 * populates the bean instance, applies post-processors, etc.
	 *
	 * 此类的中心方法:创建 bean 实例、填充 bean 实例、应用后处理器等。
	 *
	 * @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.
		//锁定class ,根据设置的 class 属性或者根据 className 来解析 Class
		// 解析得到beanClass,为什么需要解析呢?如果是从XML中解析出来的标签属性肯定是个字符串嘛
		// 所以这里需要加载类,得到Class对象
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.验证及准备覆盖的方法
		// 对XML标签中定义的lookUp属性进行预处理,
		// 如果只能根据名字找到一个就标记为非重载的,这样在后续就不需要去推断到底是哪个方法了,
		// 对于@LookUp注解标注的方法是不需要在这里处理的,
		// AutowiredAnnotationBeanPostProcessor会处理这个注解
		try {
			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.
			//给BeanPostProcessors一个露脸的机会
			// 在实例化对象前,会经过后置处理器处理
			// 这个后置处理器的提供了一个短路机制,就是可以提前结束整个Bean的生命周期,直接从这里返回一个Bean
			// 不过我们一般不会这么做,它的另外一个作用就是对AOP提供了支持,
			// 在这里会将一些不需要被代理的Bean进行标记,就本IoC系列文章而言,你可以暂时理解它没有起到任何作用
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			//若果有自定义bean则直接返回了bean,不会再走后续的doCreateBean方法
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
			// 不存在提前初始化的操作,开始正常的创建流程
			// doXXX方法,真正干活的方法,doCreateBean,真正创建Bean的方法
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			// 省略部分异常..
		}
		}
	}
初始化Class对象

很显然初始化Class对象的代码在resolveBeanClass(mbd, beanName)方法里,跟进代码查看。

	/**
	 * Resolve the bean class for the specified bean definition,
	 * resolving a bean class name into a Class reference (if necessary)
	 * and storing the resolved Class in the bean definition for further use.
	 *
	 * 为指定的 bean 定义解析 bean 类,将 bean 类名称解析为 Class 引用(如果需要)并将解析的 Class 存储在 bean 定义中以供进一步使用。
	 *
	 * @param mbd the merged bean definition to determine the class for
	 * @param beanName the name of the bean (for error handling purposes)
	 * @param typesToMatch the types to match in case of internal type matching purposes
	 * (also signals that the returned {@code Class} will never be exposed to application code)
	 *       在内部类型匹配的情况下要匹配的类型(也表示返回的 {@code Class} 永远不会暴露给应用程序代码)
	 * @return the resolved bean class (or {@code null} if none)
	 * @throws CannotLoadBeanClassException if we failed to load the class
	 */
	@Nullable
	protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
			throws CannotLoadBeanClassException {

		try {
			// 如果已经创建过,直接返回
			if (mbd.hasBeanClass()) {
				return mbd.getBeanClass();
			}
			if (System.getSecurityManager() != null) {
				return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
					doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
			}
			else {
				// 否则进行创建
				return doResolveBeanClass(mbd, typesToMatch);
			}
		}
		catch (PrivilegedActionException pae) {
			// 省略部分异常处理
		}
	}

跟进doResolveBeanClass(mbd, typesToMatch)方法,我们这里传入的typesToMatch参数对象数组为空,所以不会走排除部分类的逻辑,接下来是使用evaluateBeanDefinitionString()方法计算表达式如果传入的className有占位符,会在这里被解析,最终正常我们会走到mbd.resolveBeanClass(beanClassLoader)方法里。

	private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
			throws ClassNotFoundException {

		// 获取类加载器
		ClassLoader beanClassLoader = getBeanClassLoader();
		ClassLoader dynamicLoader = beanClassLoader;
		boolean freshResolve = false;

		if (!ObjectUtils.isEmpty(typesToMatch)) {
			// When just doing type checks (i.e. not creating an actual instance yet),
			// use the specified temporary class loader (e.g. in a weaving scenario).
			// 当只是进行类型检查(即尚未创建实际实例)时,请使用指定的临时类加载器(例如在编织场景中)。
			ClassLoader tempClassLoader = getTempClassLoader();
			if (tempClassLoader != null) {
				dynamicLoader = tempClassLoader;
				freshResolve = true;
				if (tempClassLoader instanceof DecoratingClassLoader) {
					DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
					for (Class<?> typeToMatch : typesToMatch) {
						dcl.excludeClass(typeToMatch.getName());
					}
				}
			}
		}

		String className = mbd.getBeanClassName();
		if (className != null) {
			Object evaluated = evaluateBeanDefinitionString(className, mbd);
			if (!className.equals(evaluated)) {
				// A dynamically resolved expression, supported as of 4.2...
				if (evaluated instanceof Class) {
					return (Class<?>) evaluated;
				}
				else if (evaluated instanceof String) {
					className = (String) evaluated;
					freshResolve = true;
				}
				else {
					throw new IllegalStateException("Invalid class name expression result: " + evaluated);
				}
			}
			if (freshResolve) {
				// When resolving against a temporary class loader, exit early in order
				// to avoid storing the resolved Class in the bean definition.
				// 当针对临时类加载器解析时,请提前退出以避免将解析的类存储在 bean 定义中。
				if (dynamicLoader != null) {
					try {
						// 使用临时动态加载器加载 class 对象
						return dynamicLoader.loadClass(className);
					}
					catch (ClassNotFoundException ex) {
						if (logger.isTraceEnabled()) {
							logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
						}
					}
				}
				// 反射加载 class 对象
				return ClassUtils.forName(className, dynamicLoader);
			}
		}

		// Resolve regularly, caching the result in the BeanDefinition...
		// 正常解析,将结果缓存在 BeanDefinition...
		return mbd.resolveBeanClass(beanClassLoader);
	}

跟进mbd.resolveBeanClass(beanClassLoader)方法,可以看到这里就是使用反射初始化Class对象,然后缓存在BeanDefinition中。到这里,已经完成了从一个字符串的类名到一个Class对象的转换了,我们已经得到了一个可以使用的Class对象。

	/**
	 * Determine the class of the wrapped bean, resolving it from a
	 * specified class name if necessary. Will also reload a specified
	 * Class from its name when called with the bean class already resolved.
	 *
	 * 确定被包装的 bean 的类,必要时从指定的类名解析它。当使用已解析的 bean 类调用时,还将从其名称中重新加载指定的类。
	 *
	 * @param classLoader the ClassLoader to use for resolving a (potential) class name
	 * @return the resolved bean class
	 * @throws ClassNotFoundException if the class name could be resolved
	 */
	@Nullable
	public Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {
		String className = getBeanClassName();
		if (className == null) {
			return null;
		}
		Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
		this.beanClass = resolvedClass;
		return resolvedClass;
	}
检查覆盖方法

初始化class对象已经完成了,接下来会去处理重载方法,处理的逻辑在mbdToUse.prepareMethodOverrides()方法里。

摘取《Spring源码深度解析》里面的一段话:

很多读者可能会不知道这个方法的作用,因为在 Spring 的配置里面根本就没有诸如 override-method 之类的配置, 那么这个方法到底是干什么用的呢? 其实在 Spring 中确实没有 override-method 这样的配置,但是在 Spring 配置中是存在 lookup-methodreplace-method 的,而这两个配置的加载其实就是将配置统一存放在 BeanDefinition 中的 methodOverrides 属性里,而这个函数的操作其实也就是针对于这两个配置的。

lookup-method通常称为获取器注入,spring in action 中对它的描述是,一种特殊的方法注入,它是把一个方法声明为返回某种类型的 bean,而实际要返回的 bean 是在配置文件里面配置的,可用在设计可插拔的功能上,解除程序依赖。 这里会对一些重载方法进行标记预处理,如果同方法名的方法只存在一个,那么会将覆盖标记为未重载,以避免 arg 类型检查的开销。

这种骚操作我们基本是不会使用的,所以简单看一下代码,浅尝辄止,有兴趣可以去翻翻。

	/**
	 * Validate and prepare the method overrides defined for this bean.
	 * Checks for existence of a method with the specified name.
	 *
	 * 验证并准备为此 bean 定义的方法覆盖。检查具有指定名称的方法是否存在。
	 *
	 * @throws BeanDefinitionValidationException in case of validation failure
	 */
	public void prepareMethodOverrides() throws BeanDefinitionValidationException {
		// Check that lookup methods exist and determine their overloaded status.
		// 检查查找方法是否存在并确定它们的重载状态。
		if (hasMethodOverrides()) {
			getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
		}
	}

可以看到这里就获取所有methodOverrides,然后遍历去调用prepareMethodOverride()方法,跟进prepareMethodOverride()方法。可以看到这里就是做个简单的标记。

	/**
	 * Validate and prepare the given method override.
	 * Checks for existence of a method with the specified name,
	 * marking it as not overloaded if none found.
	 *
	 * 验证并准备给定的方法覆盖。检查具有指定名称的方法是否存在,如果没有找到,则将其标记为未重载。
	 *
	 * @param mo the MethodOverride object to validate
	 * @throws BeanDefinitionValidationException in case of validation failure
	 */
	protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
		int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
		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.
			// 将覆盖标记为未重载,以避免 arg 类型检查的开销。
			mo.setOverloaded(false);
		}
	}
应用后置处理器

在实例化对象前,会经过后置处理器处理,这个后置处理器的提供了一个短路机制,就是可以提前结束整个Bean的生命周期,直接从这里返回一个Bean。不过我们一般不会这么做,它的另外一个作用就是对AOP提供了支持,在这里会将一些不需要被代理的Bean进行标记,就本IoC系列文章而言,你可以暂时理解它没有起到任何作用。

跟进代码resolveBeforeInstantiation(beanName, mbdToUse)查看。

	/**
	 * Apply before-instantiation post-processors, resolving whether there is a
	 * before-instantiation shortcut for the specified bean.
	 *
	 * 应用实例化前后处理器,解析指定 bean 是否存在实例化前快捷方式。
	 * 实例化前的快捷方式的意思这里可能会直接返回一个定义的代理,而不需要在把目标类初始化
	 *
	 * @param beanName the name of the bean
	 * @param mbd the bean definition for the bean
	 * @return the shortcut-determined bean instance, or {@code null} if none
	 */
	//注意单词Instantiation和Initialization区别
	@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()) {
				// 确定给定的 bean 的类型
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					// 提供一个提前初始化的时机,这里会直接返回一个实例对象
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						// 如果提前初始化成功,则执行 postProcessAfterInitialization() 方法,注意单词Instantiation和Initialization区别
						// 关于这一块的逻辑,细心的一点的会发现,这里漏了实例化后置处理、初始化前置处理这两个方法。
						// 而是在提前返回对象后,直接执行了初始化后置处理器就完成了bean的整个流程,
						// 相当于是提供了一个短路的操作,不再经过Spring提供的繁杂的各种处理
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			// 设置是否已经提前实例化
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

跟进applyBeanPostProcessorsBeforeInstantiation()代码查看。这里只要有一个 InstantiationAwareBeanPostProcessor 返回的结果不为空,则直接返回,说明多个 InstantiationAwareBeanPostProcessor 只会生效靠前的一个,注意单词Instantiation和Initialization区别

	/**
	 * spring bean 初始化流程
	 * Bean 初始化(Initialization)
	 * 1.@PoseConstruct 方法
	 * 2.实现InitializingBean 接口的afterPropertiesSet()方法
	 * 3.自定义初始化方法
	 */
	@Nullable
	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);
				// 如果为空,表示不作任何调整
				// 这里只要有一个 InstantiationAwareBeanPostProcessor 返回的结果不为空,则直接返回,
				// 说明多个 InstantiationAwareBeanPostProcessor 只会生效靠前的一个
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}

跟进applyBeanPostProcessorsAfterInitialization()方法,逻辑跟上面的是类似的,注意单词Instantiation和Initialization区别

	@Override
	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;
	}
创建Bean

经过上面的步骤,有惊无险,我们来到了doCreateBean(beanName, mbdToUse, args)方法,这是真正进行Bean创建的地方,所以这里才是真的进入正文,前面都是打酱油走走过程。

当经历过 resolveBeforelnstantiation() 方法后,程序有两个选择 ,如果创建了代理或者说重写了 InstantiationAwareBeanPostProcessorpostProcessBeforelnstantiation() 方法并在方法 postProcessBeforelnstantiation() 中改变了 bean, 则直接返回就可以了 , 否则需要进行常规 bean 的创建。 而这常规 bean 的创建就是在 doCreateBean() 中完成的。

直接跟进doCreateBean()代码查看,代码很长,你忍一下。

	/**
	 * Actually create the specified bean. Pre-creation processing has already happened
	 * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
	 * <p>Differentiates between default bean instantiation, use of a
	 * factory method, and autowiring a constructor.
	 *
	 * 实际创建指定的bean。
	 * 此时已经进行了预创建处理,例如检查 {@code postProcessBeforeInstantiation} 回调。
	 * <p>区分默认 bean 实例化、使用工厂方法和自动装配构造函数。
	 *
	 * @param beanName the name of the bean
	 * @param mbd the merged bean definition for the bean
	 * @param args explicit arguments to use for constructor or factory method invocation
	 * @return a new instance of the bean
	 * @throws BeanCreationException if the bean could not be created
	 * @see #instantiateBean
	 * @see #instantiateUsingFactoryMethod
	 * @see #autowireConstructor
	 */
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {
		// 这个方法真正创建了Bean,创建一个Bean会经过 创建对象 > 依赖注入 > 初始化
		// 这三个过程,在这个过程中,BeanPostProcessor会穿插执行,

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			//根据指定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.

		// 按照官方的注释来说,这个地方是Spring提供的一个扩展点,
		// 对程序员而言,我们可以通过一个实现了MergedBeanDefinitionPostProcessor的后置处理器
		// 来修改bd中的属性,从而影响到后续的Bean的生命周期
		// 不过官方自己实现的后置处理器并没有去修改bd,
		// 而是调用了applyMergedBeanDefinitionPostProcessors方法
		// 这个方法名直译过来就是-应用合并后的bd,也就是说它这里只是对bd做了进一步的使用而没有真正的修改
		synchronized (mbd.postProcessingLock) {
			// bd只允许被处理一次
			if (!mbd.postProcessed) {
				try {
					// 应用合并后的bd
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				// 标注这个bd已经被MergedBeanDefinitionPostProcessor的后置处理器处理过
				// 那么在第二次创建Bean的时候,不会再次调用applyMergedBeanDefinitionPostProcessors
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		//是否需要提前暴露mbd.isSingleton() && this.allowCircularReferences &&
		//				isSingletonCurrentlyInCreation(beanName)
		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加入工厂
			//getEarlyBeanReference对bean再一次依赖引用,主要应用SmartInstantiationAwareBeanPostProcessor
			//其中我们熟悉的AOP就是在这里将advice动态织入bean中,若没有则直接返回bean,不做任何处理
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		// 初始化实例
		Object exposedObject = bean;
		try {
			//对bean进行填充,对各个属性进行注入,可能存在依赖其他bean的属性,则会递归初始化依赖bean
			populateBean(beanName, mbd, instanceWrapper);
			//调用初始化方法
			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);
			}
		}

		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还没有被完全创建好
					 * 也就是说还存在循环依赖
					 */
					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 {
			//根据scope注册bean
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

分析一下这个函数设计思路:

  • 如果是单例则需要首先清除缓存。
  • 实例化 bean ,将 BeanDefinition 转换为 BeanWrapper。 转换是一个复杂的过程,但是我们可以尝试概括大致的功能,如下所示。
    • 如果存在工厂方法则使用工厂方法进行实例化。
    • 如果一个类有多个构造函数,每个构造函数都有不同的参数,所以需要根据参数锁定构造 函数并进行实例化。
    • 如果既不存在工厂方法也不存在带有参数的构造函数,则使用默认的构造函数进行 bean 的实例化。
  • MergedBeanDefinitionPostProcessor的应用。 bean 合并后的处理, Autowired 注解正是通过此方法实现诸如类型的预解析。
  • 依赖处理。 在 Spring 中会有循环依赖的情况,例如,当 A 中含有 B 的属性,而 B 中又含有 A 的属性 时就会构成一个循环依赖,此时如果 A 和 B 都是单例,那么在 Spring 中的处理方式就是当创建 B 的时候,涉及自动注入 A 的步骤,并不是直接去再次创建 A,而是通过放入缓存中的 ObjectFactory 来创建实例,这样就解决了循环依赖的问题。
  • 属性填充。 将所有属性填充至 bean 的实例中。
  • 调用初始化方法。在属性填充完成后,这里会进行初始化方法的调用。
  • 循环依赖检查。 之前有提到过,在 Sping 中解决循环依赖只对单例有效,而对于 prototype 的 bean, Spring 没有好的解决办法,唯一要做的就是抛出异常。 在这个步骤里面会检测已经加载的 bean 是否 已经出现了依赖循环,并判断是再需要抛出异常。
  • 注册 DisposableBean。 如果配置了 destroy-method,这里需要注册以便于在销毁时候调用。
  • 完成创建井返回。

可以看到上面的步骤非常的繁琐,每一步骤都使用了大量的代码来完成其功能,最复杂也是最难以理解的当属循环依赖的处理,在真正进入 doCreateBean() 前我们有必要先了解下循环依赖,这里会在下一篇文章Spring Ioc源码分析系列--自动注入循环依赖的处理图文并茂去分析。

下面就按照上述的点逐个分析,接下来肯定是枯燥无味的,那开始吧。

清除factoryBeanInstanceCache缓存

首先如果是单例,会到factoryBeanInstanceCache中获取是否存在缓存,如果有这里就会从缓存里获取一个instanceWrapper,不需要再去走复杂的创建流程了。

对应代码如下:

		if (mbd.isSingleton()) {
			// 你可以暂时理解为,这个地方返回的就是个null
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
实例化 bean

又到了实例化bean,是不是反反复复看了很多次,到底哪里才真的创建一个bean,别慌,这里真的是真正创建bean的地方了,再套娃就是狗。

跟进createBeanInstance(beanName, mbd, args)方法。这个方法干了哪几件事?

  • 首先尝试调用obtainFromSupplier()实例化bean
  • 尝试调用instantiateUsingFactoryMethod()实例化bean
  • 根据给定参数推断构造函数实例化bean
  • 以上均无,则使用默认构造函数实例化bean
	/**
	 * Create a new instance for the specified bean, using an appropriate instantiation strategy:
	 * factory method, constructor autowiring, or simple instantiation.
	 *
	 * 使用适当的实例化策略为指定的 bean 创建一个新实例:工厂方法、构造函数自动装配或简单实例化。
	 *
	 * @param beanName the name of the bean
	 * @param mbd the bean definition for the bean
	 * @param args explicit arguments to use for constructor or factory method invocation
	 * @return a BeanWrapper for the new instance
	 * @see #obtainFromSupplier
	 * @see #instantiateUsingFactoryMethod
	 * @see #autowireConstructor
	 * @see #instantiateBean
	 */
	protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		// 确保此时实际解析了 bean 类。
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}
		// 通过bd中提供的instanceSupplier来获取一个对象
		// 正常bd中都不会有这个instanceSupplier属性,这里也是Spring提供的一个扩展点,但实际上不常用
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		//如果工厂方法不为null,则使用工厂方法初始化策略
		// bd中提供了factoryMethodName属性,那么要使用工厂方法的方式来创建对象,
		// 工厂方法又会区分静态工厂方法跟实例工厂方法
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		// 在原型模式下,如果已经创建过一次这个Bean了,那么就不需要再次推断构造函数了
		// 是否推断过构造函数
		boolean resolved = false;
		// 构造函数是否需要进行注入
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				//一个类里面有多个构造函数,每个构造函数都有不同的参数,所以调用前需要根据参数锁定要调用的构造函数或工厂方法
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		//如果已经解析过则使用解析好的构造函数方法,不需要再次锁定
		if (resolved) {
			if (autowireNecessary) {
				//构造函数自动注入
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				//使用默认构造函数进行构造
				return instantiateBean(beanName, mbd);
			}
		}

		// Candidate constructors for autowiring?
		//需要根据参数解析构造函数
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			//构造函数自动注入
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// Preferred constructors for default construction?
		// 默认构造的首选构造函数?
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}

		// No special handling: simply use no-arg constructor.
		//使用默认构造函数
		return instantiateBean(beanName, mbd);
	}

接下来分析以上几点,算了不分析,太长了。我在另一篇文章Spring Ioc源码分析系列--实例化Bean的几种方法会填坑。这里会详细分析上面的几点,好好把握,估计看到这都不知道啥跟啥了。

MergedBeanDefinitionPostProcessor的应用

到这里我们已经实例化了一个bean对象,但是这个bean只是个半成品,空有外壳而无内在,所以接下来的工作就是对里面的内容进行填充。那毫无疑问,按照Spring的尿性,肯定会在真正开始之前给你一个扩展点,让你还要机会在属性填充之前修改某些东西。我们经常使用的@Autowired注解就是在这里实现的,后续会写一篇Spring Ioc源码分析系列--@Autowired注解的实现原理结合源码和例子去分析它的实现。

跟进代码查看,比较简单,就是获取所有的MergedBeanDefinitionPostProcessor,然后依次执行它的postProcessMergedBeanDefinition()方法。

	/**
	 * Apply MergedBeanDefinitionPostProcessors to the specified bean definition,
	 * invoking their {@code postProcessMergedBeanDefinition} methods.
	 *
	 * 将 MergedBeanDefinitionPostProcessors 应用于指定的 bean 定义,
	 * 调用它们的 {@code postProcessMergedBeanDefinition} 方法。
	 *
	 * 可以看到这个方法的代码还是很简单的,
	 * 就是调用了MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法
	 *
	 * @param mbd the merged bean definition for the bean
	 * @param beanType the actual type of the managed bean instance
	 * @param beanName the name of the bean
	 * @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
	 */
	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);
			}
		}
	}
依赖处理

这部分主要是为了处理循环依赖而做的准备,这里会根据earlySingletonExposure参数去判断是否允许循环依赖,如果允许,则会调用addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))方法将bean的早期引用放入到singletonFactories中。关于循环依赖的详细处理过程,可以在下一篇文章Spring Ioc源码分析系列--自动注入循环依赖的处理里看到。

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		//是否需要提前暴露mbd.isSingleton() && this.allowCircularReferences &&
		//				isSingletonCurrentlyInCreation(beanName)
		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加入工厂
			//getEarlyBeanReference对bean再一次依赖引用,主要应用SmartInstantiationAwareBeanPostProcessor
			//其中我们熟悉的AOP就是在这里将advice动态织入bean中,若没有则直接返回bean,不做任何处理
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

跟进addSingletonFactory()方法,可以看到这里会先把早期引用放入到singletonFactories三级缓存中。

	/**
	 * Add the given singleton factory for building the specified singleton
	 * if necessary.
	 *
	 * 如有必要,添加给定的单例工厂以构建指定的单例。
	 *
	 * <p>To be called for eager registration of singletons, e.g. to be able to
	 * resolve circular references.
	 *
	 * 被提前注册的单例Bean调用,例如用来解决循环依赖
	 *
	 * @param beanName the name of the bean
	 * @param singletonFactory the factory for the singleton object
	 */
	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);
			}
		}
	}

那放入到singletonFactories里面的是什么呢?从上面可以看到,这是一个lambada表达式,调用的方法的是getEarlyBeanReference(),跟进代码查看。

	/**
	 * Obtain a reference for early access to the specified bean,
	 * typically for the purpose of resolving a circular reference.
	 *
	 * 获取对指定 bean 的早期访问的引用,通常用于解析循环引用。
	 *
	 * @param beanName the name of the bean (for error handling purposes)
	 * @param mbd the merged bean definition for the bean
	 * @param bean the raw bean instance
	 * @return the object to expose as bean reference
	 */
	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;
					// 对 bean 再一次依赖引用
					// 主要应用 SmartInstantiationAwareBeanPostProcessor, 
					// 其中我们熟知的 AOP 就是在这里将 advice 动态织入 bean 中, 若没有则直接返回 bean ,不做任何处理
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
				}
			}
		}
		return exposedObject;
	}
属性填充

到这里会已经完成了bean的实例化,早期引用的暴露,那接下来就到了属性填充的部分,开始对bean进行各种赋值,让一个空壳半成品bean完善成一个有血有肉的正常bean。

这里可能存在依赖其他bean的属性,则会递归初始化依赖bean。

populateBean() 函数中提供了这样的处理流程。

  • InstantiationAwareBeanPostProcessor 处理器的 postProcessAfterinstantiation 函数的应用, 此函数可以控制程序是否继续进行属性填充。
  • 根据注入类型( byName/byType ),提取依赖的 bean,并统一存入 PropertyValues 中。
  • 应用 InstantiationAwareBeanPostProcessor 处理器的 postProcessPropertyValues 方法, 对属性获取完毕填充前对属性的再次处理,典型应用是 RequiredAnnotationBeanPostProcessor 类中对属性的验证。
  • 将所有 PropertyValues 中的属性填充至 BeanWrapper 中。

跟进代码查看,又很长,这一块的代码真的是又臭又长。但是注释很详细,可以跟着看看。

	/**
	 * Populate the bean instance in the given BeanWrapper with the property values
	 * from the bean definition.
	 *
	 * 使用 bean 定义中的属性值填充给定 BeanWrapper 中的 bean 实例。
	 *
	 * @param beanName the name of the bean
	 * @param mbd the bean definition for the bean
	 * @param bw the BeanWrapper with bean instance
	 */
	@SuppressWarnings("deprecation")  // for 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.
		boolean continueWithPropertyPopulation = true;

		//给InstantiationAwareBeanPostProcessors最后一次机会在属性设置前来改变 bean
		//如:可以用来支持属性注入的类型
		// 满足两个条件,不是合成类 && 存在InstantiationAwareBeanPostProcessor
		// 其中InstantiationAwareBeanPostProcessor主要作用就是作为Bean的实例化前后的钩子
		// 外加完成属性注入,对于三个方法就是
		// postProcessBeforeInstantiation  创建对象前调用
		// postProcessAfterInstantiation   对象创建完成,@AutoWired注解解析后调用
		// postProcessPropertyValues(已过期,被postProcessProperties替代) 进行属性注入
		// 下面这段代码的主要作用就是我们可以提供一个InstantiationAwareBeanPostProcessor
		// 提供的这个后置处理如果实现了postProcessAfterInstantiation方法并且返回false
		// 那么可以跳过Spring默认的属性注入,但是这也意味着我们要自己去实现属性注入的逻辑
		// 所以一般情况下,我们也不会这么去扩展
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					//返回值为是否继续填充bean
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}

		//如果后处理器发出停止填充命令则终止后续操作
		if (!continueWithPropertyPopulation) {
			return;
		}

		// 这里其实就是判断XML是否提供了属性相关配置
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		// 确认注入模型
		int resolvedAutowireMode = mbd.getResolvedAutowireMode();

		// 主要处理byName跟byType两种注入模型,byConstructor这种注入模型在创建对象的时候已经处理过了
		// 这里都是对自动注入进行处理,byName跟byType两种注入模型均是依赖setter方法
		// byName,根据setter方法的名字来查找对应的依赖,例如setA,那么就是去容器中查找名字为a的Bean
		// byType,根据setter方法的参数类型来查找对应的依赖,例如setXx(A a),就是去容器中查询类型为A的bean
		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是XML定义的属性
			// 自动注入后,bean实际用到的属性就应该要替换成自动注入后的属性
			pvs = newPvs;
		}

		//后置处理器已经初始化
		// 检查是否有InstantiationAwareBeanPostProcessor
		// 前面说过了,这个后置处理器就是来完成属性注入的
		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		//需要依赖检查
		//  是否需要依赖检查,默认是不会进行依赖检查的
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		// 下面这段代码有点麻烦了,因为涉及到版本问题
		// 其核心代码就是调用了postProcessProperties完成了属性注入
		PropertyDescriptor[] filteredPds = null;
		// 存在InstantiationAwareBeanPostProcessor,我们需要调用这类后置处理器的方法进行注入
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					// 这句就是核心
					// Autowired 是通过 AutowiredAnnotationBeanPostProcessor#postProcessProperties() 实现的
					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);
		}

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

这里看到这里会根据byName或者byType方式寻找依赖,然后调用applyPropertyValues()将属性注入到BeanWrapperImpl里。

先来看autowireByName()方法,顾名思义,这里会根据属性名去获取依赖。

	/**
	 * Fill in any missing property values with references to
	 * other beans in this factory if autowire is set to "byName".
	 * 
	 * 如果 autowire 设置为“byName”,则使用对该工厂中其他 bean 的引用填充任何缺少的属性值。
	 * 
	 * @param beanName the name of the bean we're wiring up.
	 * Useful for debugging messages; not used functionally.
	 * @param mbd bean definition to update through autowiring
	 * @param bw the BeanWrapper from which we can obtain information about the bean
	 * @param pvs the PropertyValues to register wired objects with
	 */
	protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		//寻找bw中需要依赖注入的属性值
		// 得到符合下面条件的属性名称
		// 1.有setter方法
		// 2.需要进行依赖检查
		// 3.不包含在XML配置中
		// 4.不是简单类型(基本数据类型,枚举,日期等)
		// 这里可以看到XML配置优先级高于自动注入的优先级
		// 不进行依赖检查的属性,也不会进行属性注入
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
			if (containsBean(propertyName)) {
				//递归初始化相关bean
				Object bean = getBean(propertyName);
				// 将自动注入的属性添加到pvs中去
				pvs.add(propertyName, bean);
				//注册依赖
				registerDependentBean(propertyName, beanName);
				if (logger.isTraceEnabled()) {
					logger.trace("Added autowiring by name from bean name '" + beanName +
							"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
							"' by name: no matching bean found");
				}
			}
		}
	}

接下来看autowireByType(),该方法会根据属性的类型去获取依赖。也比较简单明了。

	/**
	 * Abstract method defining "autowire by type" (bean properties by type) behavior.
	 * <p>This is like PicoContainer default, in which there must be exactly one bean
	 * of the property type in the bean factory. This makes bean factories simple to
	 * configure for small namespaces, but doesn't work as well as standard Spring
	 * behavior for bigger applications.
	 * 
	 * 定义“按类型自动装配”(按类型的 bean 属性)行为的抽象方法。 
	 * <p>这类似于 PicoContainer 默认值,其中 bean 工厂中必须只有一个属性类型的 bean。
	 * 这使得 bean 工厂易于为小型命名空间配置,但不能像标准 Spring 行为那样为大型应用程序工作。
	 * 
	 * @param beanName the name of the bean to autowire by type
	 * @param mbd the merged bean definition to update through autowiring
	 * @param bw the BeanWrapper from which we can obtain information about the bean
	 * @param pvs the PropertyValues to register wired objects with
	 */
	protected void autowireByType(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		// 这个类型转换器,主要是在处理@Value时需要使用
		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
			converter = bw;
		}

		Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
		//寻找bw中需要依赖注入的属性
		// 得到符合下面条件的属性名称
		// 1.有setter方法
		// 2.需要进行依赖检查
		// 3.不包含在XML配置中
		// 4.不是简单类型(基本数据类型,枚举,日期等)
		// 这里可以看到XML配置优先级高于自动注入的优先级
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
			try {
				PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
				// Don't try autowiring by type for type Object: never makes sense,
				// even if it technically is a unsatisfied, non-simple property.
				// 不要尝试为 Object 类型按类型自动装配:永远没有意义,即使它在技术上是一个不令人满意的、不简单的属性。
				if (Object.class != pd.getPropertyType()) {
					//探测指定属性的set方法
					// 这里获取到的就是setter方法的参数,因为我们需要按照类型进行注入嘛
					MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
					// Do not allow eager init for type matching in case of a prioritized post-processor.
					// 如果是PriorityOrdered在进行类型匹配时不会去匹配factoryBean
					// 如果不是PriorityOrdered,那么在查找对应类型的依赖的时候会会去匹factoryBean
					// 这就是Spring的一种设计理念,实现了PriorityOrdered接口的Bean被认为是一种
					// 最高优先级的 Bean,这一类的Bean在进行为了完成装配而去检查类型时,
					// 不去检查 factoryBean
					// 具体可以参考PriorityOrdered接口上的注释文档
					boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
					// 将参数封装成为一个依赖描述符
					// 依赖描述符会通过:依赖所在的类,字段名/方法名,依赖的具体类型等来描述这个依赖
					DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
					/**
					 * 解析指定beanName的属性所匹配的值,并把解析到的属性名存储在autowiredBeanNames中,
					 * 当属性存在多个封装bean时,如:
					 * @Autowire
					 * private List<A> list;
					 * 将会找到所有匹配A类型的bean并将其注入
					 * 解析依赖,这里会处理@Value注解
					 * 另外,通过指定的类型到容器中查找对应的bean
					 */
					Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
					if (autowiredArgument != null) {
						// 将查找出来的依赖属性添加到pvs中,后面会将这个pvs应用到bean上
						pvs.add(propertyName, autowiredArgument);
					}
					// 注册bean直接的依赖关系
					for (String autowiredBeanName : autowiredBeanNames) {
						//注册依赖
						registerDependentBean(autowiredBeanName, beanName);
						if (logger.isTraceEnabled()) {
							logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
									propertyName + "' to bean named '" + autowiredBeanName + "'");
						}
					}
					autowiredBeanNames.clear();
				}
			}
			catch (BeansException ex) {
				throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
			}
		}
	}

属性依赖都获取完了,接下来就是按部就班的进行注入了。

跟进applyPropertyValues()方法,逻辑比较复杂。但是最终是调用了反射,给对应的属性进行了赋值,这里深入的就不再展开了。

	/**
	 * Apply the given property values, resolving any runtime references
	 * to other beans in this bean factory. Must use deep copy, so we
	 * don't permanently modify this property.
	 *
	 * 应用给定的属性值,解析对此 bean 工厂中其他 bean 的任何运行时引用。必须使用深拷贝,所以我们不会永久修改这个属性。
	 *
	 * @param beanName the bean name passed for better exception information
	 * @param mbd the merged bean definition
	 * @param bw the BeanWrapper wrapping the target object
	 * @param pvs the new property values
	 */
	protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
		if (pvs.isEmpty()) {
			return;
		}

		if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
			((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
		}

		MutablePropertyValues mpvs = null;
		List<PropertyValue> original;

		if (pvs instanceof MutablePropertyValues) {
			mpvs = (MutablePropertyValues) pvs;
			if (mpvs.isConverted()) {
				// Shortcut: use the pre-converted values as-is.
				// 快捷方式:按原样使用转换前的值。
				try {
					bw.setPropertyValues(mpvs);
					return;
				}
				catch (BeansException ex) {
					throw new BeanCreationException(
							mbd.getResourceDescription(), beanName, "Error setting property values", ex);
				}
			}
			original = mpvs.getPropertyValueList();
		}
		else {
			original = Arrays.asList(pvs.getPropertyValues());
		}

		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
			converter = bw;
		}
		BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

		// Create a deep copy, resolving any references for values.
		// 创建一个深拷贝副本,解析任何值的引用。
		List<PropertyValue> deepCopy = new ArrayList<>(original.size());
		boolean resolveNecessary = false;
		for (PropertyValue pv : original) {
			if (pv.isConverted()) {
				deepCopy.add(pv);
			}
			else {
				String propertyName = pv.getName();
				Object originalValue = pv.getValue();
				if (originalValue == AutowiredPropertyMarker.INSTANCE) {
					Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
					if (writeMethod == null) {
						throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
					}
					originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
				}
				// 给定一个 PropertyValue,返回一个值,必要时解析对工厂中其他 bean 的任何引用
				Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
				Object convertedValue = resolvedValue;
				boolean convertible = bw.isWritableProperty(propertyName) &&
						!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
				if (convertible) {
					convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
				}
				// Possibly store converted value in merged bean definition,
				// in order to avoid re-conversion for every created bean instance.
				// 可能将转换后的值存储在合并的 bean 定义中,以避免对每个创建的 bean 实例进行重新转换。
				if (resolvedValue == originalValue) {
					if (convertible) {
						pv.setConvertedValue(convertedValue);
					}
					deepCopy.add(pv);
				}
				else if (convertible && originalValue instanceof TypedStringValue &&
						!((TypedStringValue) originalValue).isDynamic() &&
						!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
					pv.setConvertedValue(convertedValue);
					deepCopy.add(pv);
				}
				else {
					resolveNecessary = true;
					deepCopy.add(new PropertyValue(pv, convertedValue));
				}
			}
		}
		if (mpvs != null && !resolveNecessary) {
			mpvs.setConverted();
		}

		// Set our (possibly massaged) deep copy.
		// 设置我们的(可能是经过按摩的)深拷贝。
		try {
			bw.setPropertyValues(new MutablePropertyValues(deepCopy));
		}
		catch (BeansException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Error setting property values", ex);
		}
	}
调用初始化方法

初始化方法的调用逻辑在initializeBean(beanName, exposedObject, mbd)里面,跟进代码查看。

一看是不是很清晰,所以以后再遇到问你啥啥啥方法先执行,直接叼面试官。

	/**
	 *
	 * initializeBean()方法依次调用四个方法
	 * 1.invokeAwareMethods()
	 * 2.applyBeanPostProcessorsBeforeInitialization()
	 * 3.invokeInitMethods()
	 * 4.applyBeanPostProcessorsAfterInitialization()
	 *
	 */
	protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			// 1.先调用实现 aware 接口的方法
			invokeAwareMethods(beanName, bean);
		}

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

		try {
			// 3.调用初始化方法,例如实现了 InitializingBean#afterPropertiesSet() 方法
			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()) {
			// 4.最后调用 BeanPostProcessor#postProcessAfterInitialization()
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}
循环依赖检查

这一步主要是实现一个兜底的检测,避免出现注入了一个本该被代理的但是却注入了一个原生bean的情况,这部分会在循环依赖的文章里结合来分析。

先看下代码。

		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还没有被完全创建好
					 * 也就是说还存在循环依赖
					 */
					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.");
					}
				}
			}
		}
注册 DisposableBean

这也是一个回调的操作,注册一些销毁的方法。Spring 中不但提供了对于初始化方法的扩展人口 , 同样也提供了销毁方法的扩展入口,对 于销毁方法的扩展,除了我们熟知的配置属性 destroy-method 方法外,用户还可以注册后处理器 DestructionAwareBeanPostProcessor 来统一处理 bean 的销毁方法,跟进代码registerDisposableBeanIfNecessary()

	/**
	 * Add the given bean to the list of disposable beans in this factory,
	 * registering its DisposableBean interface and/or the given destroy method
	 * to be called on factory shutdown (if applicable). Only applies to singletons.
	 *
	 * 将给定的 bean 添加到该工厂的一次性 bean 列表中,
	 * 注册其 DisposableBean 接口和或在工厂关闭时调用的给定销毁方法(如果适用)。仅适用于单例。
	 *
	 * @param beanName the name of the bean
	 * @param bean the bean instance
	 * @param mbd the bean definition for the bean
	 * @see RootBeanDefinition#isSingleton
	 * @see RootBeanDefinition#getDependsOn
	 * @see #registerDisposableBean
	 * @see #registerDependentBean
	 */
	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 实现:DestructionAwareBeanPostProcessors、DisposableBean 接口、自定义销毁方法。
				/**
				 * 单例模式下需要销毁的bean,此方法中会处理实现DisposableBean的bean
				 * 并且对所有的bean使用DestructionAwareBeanPostProcessors处理
				 * DisposableBean DestructionAwareBeanPostProcessors
				 */
				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));
			}
		}
	}

总结

本文主要分析了doCreateBean()方法,但是讲得比较粗糙。回忆一下本文的思路,首先是通过类名反射得到一个class对象,然后推断构造函数去实例化得到一个bean对象,当然这部分没有深入细节去说,分多了一篇文章。然后通过byNamebyType两种方式去获取依赖注入,之后通过反射将属性注入到对象中。除去一些边边角角的校验,总的思路就是这样,还是相对清晰的,就是细节比较多。

这里牵扯的东西比较多,也算是Ioc里面比较难啃的部分了。我回看一遍我写的文章,觉得整体言不达意,脑子里想十分,说出来可能只有六分,写出来的就剩三分了。

个人水平有限,如有错误,还请指出。

如果有人看到这里,那在这里老话重提。与君共勉,路漫漫其修远兮,吾将上下而求索。

上一篇:MIT 6.824(Spring 2020) Lab1: MapReduce 文档翻译
下一篇:没有了
网友评论