《Spring源码深度分析》第5章 Bean的加载

前言

经过前面的分析,我们终于结束了对XML 配置文件的解析,接下来将会面临更大的挑战,就是对 bean 加载的探索。bean 加载的功能实现远比 bean 的解析要复杂得多。

一、Bean加载入口与源码分析

1、Bean加载的入口

讲源码之前,我们可以先来找一下源码入口。对于加载 bean 的功能,在 Spring 中的调用方式为:

MyTestBean bean = (MyTestBean) bf.getBean ("myTestBean")

这句代码实现了什么样的功能呢?我们可以先快速体验一下 Spring 中代码是如何实现的。

2、Bean加载源码

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
    
    

		/* 1、转换对应beanName。
		* 	1.去除FactoryBean的修饰符。name有可能是 &xxx 或者 xxx,如果name是&xxx,那么beanName就是xxx;
		    2.name有可能传入进来的是别名,那么beanName就是id;
		* */
		String beanName = transformedBeanName(name);
		Object beanInstance;

		/* 2、尝试从缓存中加载单例。*/
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
    
    
			if (logger.isTraceEnabled()) {
    
    
				if (isSingletonCurrentlyInCreation(beanName)) {
    
    
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
    
    
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			/* 3、返回真正的实例.
			*    缓存中记录的只是最原始的 bean 状态,并不一定是我们最终想要的 bean。
			*  举个例子:
			* (1)假如我们需要对工厂 bean 进行处理,那么这里得到的其实是工厂 bean 的初始状态,但是我们真正需要的是工厂 bean 中定义的 faetory-method 方法中返回的 bean,
			*      而 getObjectForBeanInstance 就是完成这个工作的。
			* (2)如果sharedInstance是FactoryBean且name是"&car",那么beanInstance就是调用getObject()返回的对象。
			*  */
			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		else {
    
    
			/* 4、原型模式的依赖检查(只有在单例情况才会尝试解决循环依赖;原型模式出现循环依赖会报错。)。
			*      原型模式情况下,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖,也就是isPrototypeCurrentlyInCreation (beanName)为true的情况;
			* */
			if (isPrototypeCurrentlyInCreation(beanName)) {
    
    
				throw new BeanCurrentlyInCreationException(beanName);
			}
			BeanFactory parentBeanFactory = getParentBeanFactory();

			/* 5、检测parentBeanFactory。
			 *   如果 beanDefinitionMap 中也就是在所有已经加载的类中不包括 beanName, 则尝试从parentBeanFactory 中检测,然后再去递归的调用 getBean 方法。
			 */
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    
    
				// Not found -> check parent.
				// &&&&xxx---->&xxx
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
    
    
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
    
    
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
    
    
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
    
    
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

			if (!typeCheckOnly) {
    
    
				markBeanAsCreated(beanName);
			}

			StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
					.tag("beanName", name);
			try {
    
    
				if (requiredType != null) {
    
    
					beanCreation.tag("beanType", requiredType::toString);
				}
				/* 6、将存储 XML 配置文件的 GenericBeanDefinition 转换为 RootBeanDefinition。
				*    1.因为从 XML 配置文件中该取到的 Bean 信息是存储在 GenericBeanDefinition 中的,但是所有的 Bean 后续处理都是针对于 RootBeanDefinition 的,所以这里需要进行一个转换;
				*    2.转换的同时如果父类 bean 不为空的话,则会一并合并交类的属性。
				* */
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

				// 检查BeanDefinition是不是Abstract的
				checkMergedBeanDefinition(mbd, beanName, args);

				/* 7、寻找依赖。
				*    因为 bean 的初始化过程中很可能会用到某些属性,而某些属性很可能是动态配置的,并且配置成依赖于其他的 bean,那么这个时候就有必要先加载依赖的 bean,
				* 所以,在 Spring 的加载顺寻中,在初始化某一个 bean 的时候首先会初始化这个 bean 所对应的依赖。
				* */
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
    
    
					// dependsOn表示当前beanName所依赖的,当前Bean创建之前dependsOn所依赖的Bean必须已经创建好了
					for (String dep : dependsOn) {
    
    
						// beanName是不是被dep依赖了,如果是则出现了循环依赖
						if (isDependent(beanName, dep)) {
    
    
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						// dep被beanName依赖了,存入dependentBeanMap中,dep为key,beanName为value
						registerDependentBean(dep, beanName);

						// 创建所依赖的bean
						try {
    
    
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
    
    
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}
				/* 8、针对不同的scope模式进行bean的创建*/
				// 8.1.singleton模式的创建
				if (mbd.isSingleton()) {
    
    
					sharedInstance = getSingleton(beanName, () -> {
    
    
						try {
    
    
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
    
    
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				// 8.2.prototype模式的创建
				else if (mbd.isPrototype()) {
    
    
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
    
    
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
    
    
						afterPrototypeCreation(beanName);
					}
					beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}
				// 8.3.	其他scope类型
				else {
    
    
					String scopeName = mbd.getScope();
					if (!StringUtils.hasLength(scopeName)) {
    
    
						throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
					}
					Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
    
    
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
    
      // session.getAttriute(beaName)  setAttri
						Object scopedInstance = scope.get(beanName, () -> {
    
    
							beforePrototypeCreation(beanName);
							try {
    
    
								return createBean(beanName, mbd, args);
							}
							finally {
    
    
								afterPrototypeCreation(beanName);
							}
						});
						beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
    
    
						throw new ScopeNotActiveException(beanName, scopeName, ex);
					}
				}
			}
			catch (BeansException ex) {
    
    
				beanCreation.tag("exception", ex.getClass().toString());
				beanCreation.tag("message", String.valueOf(ex.getMessage()));
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
			finally {
    
    
				beanCreation.end();
			}	
		}

		/* 9、类型转换。
		*     1.程序到这里返回 bean后已经基本结束了,通常对该方法的调用参数 requiredType 是为空的,
		* 但是可能会存在这样的情况,返回的 bean 其实是个 String,但是 requiredType 却传入 Integer类型,那么这时候本步骤就会起作用了,
		* 它的功能是将返回的 bean 转换为 requiredType 所指定的类型。
		*     2.当然,String 转换为 Integer 是最简单的一种转换,在 Spring 中提供了各种各样的转换器,用户也可以自己扩展转换器来满足需求。
		* */
		return adaptBeanInstance(name, beanInstance, requiredType);
	}

经过上面的步骤后 bean 的加载就结束了,这个时候就可以返回我们所需要的 bean 了。其中最重要的就是步骤(8),针对不同的 scope 进行 bean 的创建,你会看到各种常用的 Spring 特性在这里的实现

在细化分析各个步骤提供的功能前,我们有必要先了解下 FactoryBean 的用法。

二、FactoryBean的使用

【Spring学习】FactoryBean的使用

三、缓存中获取单例bean(待补充)

四、准备创建bean(createBean方法)

我们不可能指望在一个函数中完成一个复杂的逻辑,而且我们跟踪了这么多 Spring 代码,经历了这么多函数,或多或少也发现了一些规律:一个真正干活的函数其实是以 do 开头的。这个规则对于 createBean 也不例外,那么让我们看看在createBean 函数中做了哪些准备工作。

createBean方法

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.
		// 马上就要实例化Bean了,确保beanClass被加载了
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    
    
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
		try {
    
    
			// 针对lookup-method 和 replace-method
			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.
			/**
			* 实例化前置处理:对BeanDefinition的'属性'进行前置化处理。
			* */
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
    
    
				return bean;
			}
		}
		catch (Throwable ex) {
    
    
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
    
    
			/**
			 * 开始创建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);
		}
	}

Bean前置处理(重要)

在真正调用doCreate 方法创建 bean 的实例前使用了这样一个方法 resolveBeforelnstantiation(beanName, mbd)对 BeanDefinigiton 中的属性做些前置处理。当然,无论其中是否有相应的逻辑实现我们都可以理解,因为真正逻辑实现前后留有处理函数也是可扩展的一种体现

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.
			// synthetic表示合成,如果某些Bean式合成的,那么则不会经过BeanPostProcessor的处理
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    
    
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
    
    
					// 真正调用'实例化前'方法的地方。
					// 此处会获取postProcessBeforeInstantiation返回的对象,如果对象不为null则直接执行'初始化后'。
					/**
					 * bean 的实例化前调用,也就是将 'AbstractBeanDefinition 转换为 Bean Wrapper 前'的处理。给子类一个修改 BeanDefinition 的机会,
					 * 也就是说当程序经过这个方法后,bean 可能已经不是我们认为的 bean 了,而是或许成为了一个'经过处理的代理 bean',可能是'通过 cglib 生成'的,
					 * 也可能是'通过其它技术生成'的。这在第 7 章中会详细介绍,我们只需要知道,在 bean 的实例化前会调用后处理器的方法进行处理。
					 */
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					/**
					 * 当经过前置处理后返回的结果如果不为空,那么会直接略过后续的 Bean 的创建而直接返回结果。
					 * 这一特性虽然很容易被忽略,但是却起着至关重要的作用,我们熟知的 AOP 功能就是其干这电的判新的.
					 */
					if (bean != null) {
    
    
						/**
						 * 在讲解'从缓存中获取单例 bean '的时候就提到过,Spring 中的规则是在 bean 的初始化后尽可能保证将注册的后处理器的 postProcessAfterInitialization 方法应用到该 bean 中,
						 * 因为如果返回的 bean 不为空,那么便不会再次经历普通 bean 的创建过程,所以只能在这里应用后处理器的 postProcessAfterInitialization 方法。
						 */
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

五、循环依赖

实例化 bean 是一个非常复杂的过程,而其中最比较难以理解的就是对循环依赖的解决,不管之前读者有没有对循环依赖方面的研究,这里有必要先对此知识点稍作回顾。

扫描二维码关注公众号,回复: 14613186 查看本文章

什么是循环依赖

循环依赖就是循环引用,就是两个或多个 bean 相互之间的持有对方,比如 CircleA 引用CircleB, CircleB 引用 Circlec, Circlec 引用 CircleA,则它们最终反映为一个环。如图5-2 所示。
在这里插入图片描述

循环依赖不是循环调用,循环调用是方法之间的环调用,循环调用是无法解决的,除非有终结条件,否则就是死循环,最终导致内存溢出错误

Spring如何解决循环依赖

Spring 容器循环依赖包括构造器循环依赖setter 循环依赖,那 Spring 容器如何解决循环依赖呢?首先让我们来定义循环引用类:

package com.cms.circulardep;

/**
 * @author: coffee
 * @date: 2023/4/1 10:28 PM
 * @description: ...
 */
public class TestA {
    
    
    private TestB testB;

    public TestB getTestB() {
    
    
        return testB;
    }

    public void setTestB(TestB testB) {
    
    
        this.testB = testB;
    }
}

package com.cms.circulardep;

/**
 * @author: coffee
 * @date: 2023/4/1 10:28 PM
 * @description: ...
 */
public class TestB {
    
    
    private TestC testC;

    public TestC getTestC() {
    
    
        return testC;
    }

    public void setTestC(TestC testC) {
    
    
        this.testC = testC;
    }
}

package com.cms.circulardep;

/**
 * @author: coffee
 * @date: 2023/4/1 10:28 PM
 * @description: ...
 */
public class TestC {
    
    
    private TestA testA;

    public TestA getTestA() {
    
    
        return testA;
    }

    public void setTestA(TestA testA) {
    
    
        this.testA = testA;
    }
}

spring将循环依赖分为三种情况。

1. 构造器循环依赖

表示通过构造器注入构成的循环依赖,此依赖是无法解决的,只能抛出 BeanCurrentlyinCreationException 异常表示循环依赖。

Spring 容器将每一个正在创建的 bean 标识符放在一个“当前创建 bean 池”中,bean 标识符在创建过程中将一直保持在这个池中,因此如果在创建 bean 过程中发现自己已经在“当前创建 bean 池”里时,将抛出 BeanCurrentlyInCreationException 异常表示循环依赖;面对于创建完毕的 bean 将从“当前创建 bean 池”中清除掉

我们可以通过一个示例来分析。
(1)创建xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="testA" class="com.cms.circulardep.TestA">
        <constructor-arg index="0" ref="testB"/>
    </bean>

    <bean id="testB" class="com.cms.circulardep.TestB">
        <constructor-arg index="0" ref="testC"/>
    </bean>

    <bean id="testC" class="com.cms.circulardep.TestC">
        <constructor-arg index="0" ref="testA"/>
    </bean>
</beans>

(2)创建测试用例

package com.cms.circulardep;

import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author: coffee
 * @date: 2023/4/1 10:35 PM
 * @description: ...
 */
public class CircularDepTest {
    
    

    @Test
    public void test () {
    
    
        try {
    
    
            new ClassPathXmlApplicationContext("com/cms/circulardep/constructor.xml");
        } catch (Exception e) {
    
    
            // 因为在创建testC的时候抛出异常
            Throwable t = e.getCause().getCause().getCause();
        }
    }
}

(3)针对以上代码的分析如下:

  • Spring 容器创建 “testA” bean,首先去“当前创建 bean 池”查找是否当前 bean 正在创建,如果没发现,则继续准备其需要的构造器参数 “testB”,并将 “testA”标识符放到“当前创建 bean 池”。
  • Spring 容器创建 “testB” bean,首先去“当前创建 bean 池”查找是否当前 bean 正在创建,如果没发现,则继续准备其需要的构造器参数 “testC”,并将 “testB” 标识符放到“当前创建 bean 池”。
  • Spring 容器创建 “testC” bean,首先去 “当前创建 bean 池”查找是否当前 bean 正在创建,如果没发现,则继续准备其需要的构造器参数 “testA”,并将 “testC” 标识符放到“当前创建 Bean 池”。
  • 到此为止 Spring 容器要去创建 “testA” bean,发现该 bean 标识符在“当前创建 bean池”中,因为表示循环依赖,抛出 BeanCurrentlyinCreationException.

2. setter 循环依赖

表示通过 setter 注入方式构成的循环依赖。对于 setter 注入造成的依赖是通过 Spring 容器 提前暴露 刚完成构造器注入 但末完成其他步骤(如 setter 注入)的 bean 来完成的,而且只能解决单例作用域的 bean 循环依赖。通过提前暴露一个单例工厂方法,从而使其他 bean 能引用到该 bean,如下代码所示:
在这里插入图片描述具体步骤如下。
(1)Spring 容器创建单例“testA” bean,首先根据无参构造器创建 bean,并暴露一个"ObjectFactory” 用于返回一个提前暴露一个创建中的 bean,并将“testA” 标识符放到“当前创建 bean 池”,然后进行 setter 注人 “testB”。
(2) Spring 容器创建单例 “testB” bean,首先根据无参构造器创建 bean,并暴露一个“ObjeetFactory"用于返回一个提前暴露一个创建中的 bean,并将 “testB” 标识符放到“当前创建 bean 池”,然后进行 setter 注入 “circle”。
(3) Spring 容器创建单例“testC” bean,首先根据无参构造器创建 bean,并暴露一个“ObjectFactory”用于返回一个提前暴露一个创建中的 bean,并将“testc”标识符放到“当前创建bean 池”,然后进行 setter注人“testA”。进行注人“testA” 时由于提前暴露了 “ObjieetFactory“工厂,从而使用它返回提前暴露一个创建中的 bean
(4)最后在依赖注入 “testB” 和 “testA” 完成 setter 注入 。

3. prototype 范围的依赖处理

对于 “prototype”作用城 bean,Spring 容器无法完成依赖注入,因为-Spring 容器不进行缓存“prototype”作用域的 bean,因此无法提前暴露一个创建中的 bean。示例如下:
(1)创建配置文件。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="testA" class="com.cms.circulardep.TestA" scope="prototype">
        <constructor-arg index="0" ref="testB"/>
    </bean>

    <bean id="testB" class="com.cms.circulardep.TestB" scope="prototype">
        <constructor-arg index="0" ref="testC"/>
    </bean>

    <bean id="testC" class="com.cms.circulardep.TestC" scope="prototype">
        <constructor-arg index="0" ref="testA"/>
    </bean>
</beans>

(2)测试类

    @Test
    public void prototypeTest () {
    
    
        try {
    
    
            new ClassPathXmlApplicationContext("com/cms/circulardep/prototype.xml");
        } catch (Exception e) {
    
    
            Throwable t = e.getCause().getCause().getCause();
        }
    }

禁用循环依赖

对于 “singleton” 作用域 bean,可以通过 “setAllowCircularReferences(false);”来禁用循环依赖。

六、创建bean

doCreateBean方法

源码

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

		// 实例化bean
		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
    
    
			// 有可能在本Bean创建之前,就有其他Bean把当前Bean给创建出来了(比如依赖注入过程中)
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
    
    
			/**
			 * 创建bean实例。根据指定bean使用对应的策略创建新的实例,如:工厂方法、构造方法自动注入、简单初始化
			 */
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
    
    
			mbd.resolvedTargetType = beanType;
		}

		// 后置处理合并后的BeanDefinition
		// Allow post-processors to modify the merged bean definition.
		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;
			}
		}

		/**
		 * 为了解决循环依赖提前缓存单例创建工厂。
		 */
		// 是否需要提早曝光:(单例 && 允许循环依赖 && 当前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");
			}
			// 循环依赖-添加到三级缓存。为避免后期循环依赖,可以在' bean初始化完成前'将创建实例的ObjectFactory加入工厂
			addSingletonFactory(beanName, () ->
					// 对 bean 再一次依赖引用,主要应用 SmartInstantiationAware BeanPostProcessor, 其中我们熟知的 AOP 就是在这里将 advice 动态织人 bean 中,若没有则直接返回bean,不做任何处理
					getEarlyBeanReference(beanName, mbd, bean)
			);
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
    
    
			/**
			 * 属性填充  (自动注入)
			 */
			populateBean(beanName, mbd, instanceWrapper);
			/**
			 * 调用初始化方法 (aware回调、初始化前、初始化、初始化后)
			 */
			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) {
    
    
				if (exposedObject == bean) {
    
    
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
    
    
					// beanName被哪些bean依赖了,现在发现beanName所对应的bean对象发生了改变,那么则会报错
					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 创建后其依赖的 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 " +
								"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
    
    
			/**
			 * 只做一件事情:注册实现了'销毁'方法的bean。
			 */
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
    
    
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

流程分析

尽管日志与异常的内容非常重要,但是在阅读源码的时候似乎大部分人都会直接忽略掉。在此不深人探讨日志及异常的设计,我们看看整个函数的概要思路。
(1)如果是单例则需要首先清除缓存。
(2) 实例化 bean,将 BeanDefinition 转换为 Bean Wrapper
转换是一个复杂的过程,但是我们可以尝试概括大致的功能,如下所示:

  • 如果存在工厂方法则使用工厂方法进行初始化。
  • 一个类有多个构造函数,每个构造函数都有不同的参数,所以需要根据参数锁定构造函数并进行初始化。
  • 如果既不存在工厂方法也不存在带有参数的构造函数,則使用默认的构造函数进行bean 的实例化。

(3) MergedBeanDefinitionPostProcessor 的应用。
bean 合并后的处理,Autowired 注解正是通过此方法实现诸如类型的预解析。
(4) 依赖处理。
在 Spring 中会有循环依赖的情况,例如,当A中含有B的属性,而B中又含有A的属性时就会构成一个循环依赖,此时如果 A 和 B都是单例,那么在 Spring 中的处理方式就是当创建B的时候,涉及自动注入 A 的步骤时,并不是直接去再次创建 A,而是通过放入缓存中的ObjectFactory 来创建实例,这样就解决了循环依赖的问题。
(5)属性填充。将所有属性填充至 bean 的实例中
(6) 循环依赖检查。
之前有提到过,在 Sping 中解决循环依赖只对单例有效,而对于 prototype 的 bean, Spring没有好的解决办法,唯一要做的就是抛出异常。在这个步骤里面会检测已经加载的 bean 是否已经出现了依赖循环,并判断是否需要抛异常。
(7)注册 DisposableBean。
如果配置了 destroy-method,这里需要注册以便于在销毁时候调用
(8)完成创建并返回。

可以看到上面的步骤非常的繁琐,每一步骤都使用了大量的代码来完成其功能,最复杂也是最难以理解的当属循环依赖的处理,在真正进入 doCreateBean 前我们有必要先了解下循环依赖

创建bean的实例

源码

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    
    
		// Make sure bean class is actually resolved at this point.
		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());
		}

		// BeanDefinition中添加了Supplier,则调用Supplier来得到对象
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
    
    
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		/** 如果工厂方法不为空,则使用工厂方法初始化策略 */
		// @Bean对应的BeanDefinition.  factoryMethodName是@Bean修饰的方法的名字,factoryBean就是config类对象
		if (mbd.getFactoryMethodName() != null) {
    
    
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		// 一个原型BeanDefinition,会多次来创建Bean,那么就可以把该BeanDefinition所要使用的构造方法缓存起来,避免每次都进行构造方法推断
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
    
    
			synchronized (mbd.constructorArgumentLock) {
    
    
				/**  一个类有多个构造函数,每个构造函数都有不同的参数,所以调用前需要先根据参数锁定构造函数或对应的工厂方法 */
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
    
    
					resolved = true;
					// autowireNecessary表示有没有必要要进行注入,比如当前BeanDefinition用的是无参构造方法,那么autowireNecessary为false,否则为true,表示需要给构造方法参数注入值
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		/** 如果已经解析过则使用解析好的构造函数方法,不需要再次锁定*/
		if (resolved) {
    
    
			// 如果确定了当前BeanDefinition的构造方法,那么看是否需要进行对构造方法进行参数的依赖注入(构造方法注入)
			if (autowireNecessary) {
    
    
				/** 构造函数自动注入 */
				// 方法内会拿到缓存好的构造方法的入参
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
    
    
				/** 使用默认构造函数 */
				// 构造方法已经找到了,但是没有参数,那就表示是无参,直接进行实例化
				return instantiateBean(beanName, mbd);
			}
		}

		/**
		 * 需要根据参数,解析构造函数
		 * */
		// 如果没有找过构造方法,那么就开始找了
		// 提供一个扩展点,可以利用SmartInstantiationAwareBeanPostProcessor来控制用beanClass中的哪些构造方法
		// 比如AutowiredAnnotationBeanPostProcessor会把加了@Autowired注解的构造方法找出来,具体看代码实现会更复杂一点
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

		// 如果推断出来了构造方法,则需要给构造方法赋值,也就是给构造方法参数赋值,也就是构造方法注入
		// 如果没有推断出来构造方法,但是autowiremode为AUTOWIRE_CONSTRUCTOR,则也可能需要给构造方法赋值,因为不确定是用无参的还是有参的构造方法
		// 如果通过BeanDefinition指定了构造方法参数值,那肯定就是要进行构造方法注入了
		// 如果调用getBean的时候传入了构造方法参数值,那肯定就是要进行构造方法注入了
		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);
		}

		/** 使用默认构造函数 */
		// 不匹配以上情况,则直接使用无参构造方法
		return instantiateBean(beanName, mbd);
	}

流程分析

(1)如果在 RootBeanDefinition 中存在 factoryMethodName 属性,或者说在配置文件中配置了 factory-method,那么 Spring 会尝试使用 instantiateUsingFactoryMethod(beanName, mbd, args)方法根据 RootBeanDefinition 中的配置生成 bean 的实例

(2)解析构造函数并进行构造函数的实例化因为一个 bean 对应的类中可能会有多个构造函数,而每个构造函数的参数不同,Spring 在根据参数及类型去判断最终会使用哪个构造函数进行实例化。但是,判断的过程是个比较消耗性能的步骤,所以采用缓存机制,如果已经解析过则不需要重复解析而是直接从 RootBeanDefinition 中的属性resolvedConstructorOrFactoryMethod缓存的值去取,否则需要再次解析,并将解析的结果添加至 RootBeanDefinition 中的属性resolvedConstructorOrFactoryMethod 中。

1.autowireConstructor(有参构造)

对于实例的创建 Spring 中分成了两种情况,一种是通用的实例化,另一种是带有参数的实例化。带有参数的实例化过程相当复杂,因为存在着不确定性,所以在判断对应参数上做了大量工作

源码

public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
			@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
    
    

		BeanWrapperImpl bw = new BeanWrapperImpl();
		this.beanFactory.initBeanWrapper(bw);

		Constructor<?> constructorToUse = null;
		ArgumentsHolder argsHolderToUse = null;
		Object[] argsToUse = null;

		// 如果getBean()调用的时候指定方法参数,那么直接使用
		if (explicitArgs != null) {
    
    
			argsToUse = explicitArgs;
		}
		else {
    
    
			// 如果在getBean方法时候没有指定方法参数,则尝试从配置文件中解析
			Object[] argsToResolve = null;
			synchronized (mbd.constructorArgumentLock) {
    
    
				constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse != null && mbd.constructorArgumentsResolved) {
    
    
					// 从缓存中取
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
    
    
						// 配置的构造函数参数
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			// 如果缓存中存在
			if (argsToResolve != null) {
    
    
				// 解析参数类型,如给定方法的构造函数A(int,int),则通过此方法后就会把配置中的("1","1")转换为(1,1)
				// 缓存中的值可能是原始值,也可能是最终值
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
			}
		}

		// 没有被缓存。如果没有确定要使用的构造方法,或者确定了构造方法但是所要传入的参数值没有确定
		if (constructorToUse == null || argsToUse == null) {
    
    

			// Take specified constructors, if any.
			// 如果没有指定构造方法,那就获取beanClass中的所有构造方法所谓候选者
			Constructor<?>[] candidates = chosenCtors;
			if (candidates == null) {
    
    
				Class<?> beanClass = mbd.getBeanClass();
				try {
    
    
					candidates = (mbd.isNonPublicAccessAllowed() ?
							beanClass.getDeclaredConstructors() : beanClass.getConstructors());
				}
				catch (Throwable ex) {
    
    
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Resolution of declared constructors on bean Class [" + beanClass.getName() +
							"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
				}
			}

			// 如果只有一个候选构造方法,并且没有指定所要使用的构造方法参数值,并且该构造方法是无参的,那就直接用这个无参构造方法进行实例化了
			if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
    
    
				Constructor<?> uniqueCandidate = candidates[0];
				if (uniqueCandidate.getParameterCount() == 0) {
    
    
					synchronized (mbd.constructorArgumentLock) {
    
    
						mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
						mbd.constructorArgumentsResolved = true;
						mbd.resolvedConstructorArguments = EMPTY_ARGS;
					}
					bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
					return bw;
				}
			}

			// Need to resolve the constructor.
			boolean autowiring = (chosenCtors != null ||
					mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
			ConstructorArgumentValues resolvedValues = null;

			// 确定要选择的构造方法的参数个数的最小值,后续判断候选构造方法的参数个数如果小于minNrOfArgs,则直接pass掉
			int minNrOfArgs;
			if (explicitArgs != null) {
    
    
				// 如果直接传了构造方法参数值,那么所用的构造方法的参数个数肯定不能少于
				minNrOfArgs = explicitArgs.length;
			}
			else {
    
    
				// 提前配置文件中的配置的构造方法参数。如果通过BeanDefinition传了构造方法参数值,因为有可能是通过下标指定了,比如0位置的值,2位置的值,虽然只指定了2个值,但是构造方法的参数个数至少得是3个
				ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
				// 用于承载解析后的构造函数参数的值
				resolvedValues = new ConstructorArgumentValues();
				// 能解析到的参数个数
				minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
			}

			// 对候选构造方法进行排序,public的方法排在最前面,都是public的情况下参数个数越多越靠前
			AutowireUtils.sortConstructors(candidates);
			int minTypeDiffWeight = Integer.MAX_VALUE;
			Set<Constructor<?>> ambiguousConstructors = null;
			Deque<UnsatisfiedDependencyException> causes = null;

			// 遍历每个构造方法,进行筛选
			for (Constructor<?> candidate : candidates) {
    
    
				// 参数个数
				int parameterCount = candidate.getParameterCount();

				if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
    
    
					// 如果已经找到选用的构造函数或者需要的参数个数小于当前的构造两数参数个数则终止,因为已经按照参数个数降序排列
					break;
				}
				if (parameterCount < minNrOfArgs) {
    
    
					// 如果参数个数小于所要求的参数个数,则遍历下一个。这里考虑的是同时存在public和非public的构造方法
					continue;
				}

				ArgumentsHolder argsHolder;
				Class<?>[] paramTypes = candidate.getParameterTypes();
				// 没有通过getBean()指定构造方法参数值
				if (resolvedValues != null) {
    
    
					try {
    
    
						// 注解上获取参数名称。如果在构造方法上使用了@ConstructorProperties,那么就直接取定义的值作为构造方法的参数名
						String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);

						if (paramNames == null) {
    
    
							// 获取构造方法参数名
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
							if (pnd != null) {
    
    
								// 获取指定构造函数的参数名称
								paramNames = pnd.getParameterNames(candidate);
							}
						}

						// 根据参数类型、参数名找到对应的bean对象
						argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
								getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
					}
					catch (UnsatisfiedDependencyException ex) {
    
    
						// 当前正在遍历的构造方法找不到可用的入参对象,记录一下
						if (logger.isTraceEnabled()) {
    
    
							logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
						}
						// Swallow and try next constructor.
						if (causes == null) {
    
    
							causes = new ArrayDeque<>(1);
						}
						causes.add(ex);
						continue;
					}
				}
				else {
    
    
					// Explicit arguments given -> arguments length must match exactly.
					// 没有通过BeanDefinition指定构造方法参数值,但是在调getBean方法是传入了参数值,那就表示只能用对应参数个数的构造方法
					if (parameterCount != explicitArgs.length) {
    
    
						continue;
					}
					// 不用再去BeanFactory中查找bean对象了,已经有了,同时当前正在遍历的构造方法就是可用的构造方法
					argsHolder = new ArgumentsHolder(explicitArgs);
				}

				// 当前遍历的构造方法所需要的入参对象都找到了,根据参数类型和找到的参数对象计算出来一个匹配值,值越小越匹配
				// Lenient表示宽松模式
				int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
						argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
				// Choose this constructor if it represents the closest match.
				// 值越小越匹配
				if (typeDiffWeight < minTypeDiffWeight) {
    
    
					constructorToUse = candidate;
					argsHolderToUse = argsHolder;
					argsToUse = argsHolder.arguments;
					minTypeDiffWeight = typeDiffWeight;
					ambiguousConstructors = null;
				}
				// 值相等的情况下,记录一下匹配值相同的构造方法
				else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
    
    
					if (ambiguousConstructors == null) {
    
    
						ambiguousConstructors = new LinkedHashSet<>();
						ambiguousConstructors.add(constructorToUse);
					}
					ambiguousConstructors.add(candidate);
				}
			}
			// 遍历结束   x

			// 如果没有可用的构造方法,就取记录的最后一个异常并抛出
			if (constructorToUse == null) {
    
    
				if (causes != null) {
    
    
					UnsatisfiedDependencyException ex = causes.removeLast();
					for (Exception cause : causes) {
    
    
						this.beanFactory.onSuppressedException(cause);
					}
					throw ex;
				}
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Could not resolve matching constructor on bean class [" + mbd.getBeanClassName() + "] " +
						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
			}
			// 如果有可用的构造方法,但是有多个
			else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
    
    
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Ambiguous constructor matches found on bean class [" + mbd.getBeanClassName() + "] " +
						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
						ambiguousConstructors);
			}

			// 将解析的构造函数进行缓存。如果没有通过getBean方法传入参数,并且找到了构造方法以及要用的入参对象则缓存
			if (explicitArgs == null && argsHolderToUse != null) {
    
    
				argsHolderToUse.storeCache(mbd, constructorToUse);
			}
		}

		Assert.state(argsToUse != null, "Unresolved constructor arguments");
		// 将创建的实例加入到BeanWrapper中
		bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
		return bw;
	}

流程分析

这里要先吐个槽,笔者觉得这个函数的写法完全不符合 Spring 的一贯风格,如果你一直跟随笔者的分析思路到这里,相信你或多或少对 Spring 的编码风格有所了解,Spring 的一贯做法是将复杂的逻辑分解,分成N 个小函数的嵌套,每一层都是对下一层逻辑的总结及概要,这样使得每一层的逻辑会变得简单容易理解。在上面的函数中,包含着很多的逻辑实现,笔者觉得至少应该将逻辑封装在不同函数中而使得在 autowireConstructor 中的逻辑清晰明了。

(1)构造函数参数的确定。

  1. 根据 explicitArgs 参数判断。

如果传人的参数 explicitArgs 不为空,那边可以直接确定参数,因为 explicitArgs 参数是在调用 Bean 的时候用户指定的,在 BeanFactory 类中存在这样的方法:
Object getBean (String name, Object… args) throws BeansException;
在获取 bean 的时候,用户不但可以指定 bean 的名称还可以指定 bean 所对应类的构造函数或者工厂方法的方法参数, 主要用于静态工厂方法的调用,而这里是需要给定完全匹配的参数的,所以,便可以判断,如果传入参数 explicitArgs 不为空,则可以确定构造函数参数就是它。

  1. 缓存中获取。

除此之外,确定参数的办法如果之前已经分析过,也就是说构造函数参数已经记录在缓存中,那么便可以直接拿来使用。而且,这里要提到的是,在缓存中缓存的可能是参数的最终型也可能是参数的初始类型,例如:构造函数参数要求的是 int 类型,但是原始的参数值可能是 String 类型的“1”,那么即使在绶存中得到了参数,也需要经过类型转换器的过滤以确保参数类型与对应的构造函数参数类型完全对应。

  1. 配置文件获取。

如果不能根据传入的参数 explicitArgs 确定构造函数的参数也无法在缓存中得到相关信息,那么只能开始新一轮的分析了。
分析从获取配置文件中配置的构造函数信息开始,经过之前的分析,我们知道,Spring 中配置文件中的信息经过转换都会通过 BeanDefinition 实例承载,也就是参数 mbd 中包含,那么可以通过调用 mbd.getConstructorArgumentValues()来获取配置的构造函数信息。有了配置中的信息便可以获取对应的参数值信息了,获取参数值的信息包括直接指定值,如:直接指定构造函数中某个值为原始类型 String 类型,或者是一个对其他 bean 的引用,而这一处理委托给resolveConstructorArguments 方法,并返回能解析到的参数的个数。

(2)构造函数的确定。
经过了第一步后已经确定了构造函数的参数,接下来的任务就是根据构造函数参数在所有造函数中锁定对应的构造函数,而匹配的方法就是根据参数个数匹配,所以在匹配之前需要先对构造函数按照 public 构造函数优先参数数量降序、非 public 构造函数参数数量降序。这样可以在遍历的情况下迅速判断排在后面的构造函数参数个数是否符合条件。

由于在配置文件中并不是唯一限制使用参数位置索引的方式去创建,同样还支持指定参数名称进行设定参数值的情况,如,那么这种情况就需要首先确定构造函数中的参数名称。

获取参数名称可以有两种方式,一种是通过注解的方式直接获取,另一种就是使用 Spring中提供的工具类 ParameterNameDiscoverer 来获取。构造函数、参数名称、参数类型、参数值都确定后就可以锁定构造函数以及转换对应的参数类型了。

(3)根据确定的构造函数转换对应的参数类型。
主要是使用 Spring 中提供的类型转换器或者用户提供的自定义类型转换器进行转换。

(4)构造函数不确定性的验证。
当然,有时候即使构造函数、参数名称、参数类型、参数值都确定后也不一定会直接锁定构造兩数,不同构造函数的参数为交子关系,所以 Spring 在最后又做了一次验证。

(5)根据实例化策略以及得到的构造函数及构造函数参数实例化 Bean。后面章节中将进行讲解。

2. instantiateBean(无参构造)

经历了带有参数的构造函数的实例构造,相信你会非常轻松愉快地理解不带参数的构造函数的实例化过程。

protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
    
    
		try {
    
    
			Object beanInstance;
			if (System.getSecurityManager() != null) {
    
    
				beanInstance = AccessController.doPrivileged(
						(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
						getAccessControlContext());
			}
			else {
    
    
				// 默认是CglibSubclassingInstantiationStrategy
				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
			}
			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
			initBeanWrapper(bw);
			return bw;
		}
		catch (Throwable ex) {
    
    
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
		}
	}

你会发现,此方法并没有什么实质性的逻辑,带有参数的实例构造中,Spring 把精力都放在了构造函数以及参数的匹配上,所以如果没有参数的话那将是非常简单的一件事,直接调用实例化策略进行实例化就可以了。

记录创建 bean 的 ObjectFactory

在 doCreate 函数中有这样一段代码:

	    /**
		 * 为了解决循环依赖提前缓存单例创建工厂。
		 */
		// 是否需要提早曝光:(单例 && 允许循环依赖 && 当前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");
			}
			// 循环依赖-添加到三级缓存。为避免后期循环依赖,可以在' bean初始化完成前'将创建实例的ObjectFactory加入工厂
			addSingletonFactory(beanName, () ->
					// 对 bean 再一次依赖引用,主要应用 SmartInstantiationAware BeanPostProcessor, 其中我们熟知的 AOP 就是在这里将 advice 动态织人 bean 中,若没有则直接返回bean,不做任何处理
					getEarlyBeanReference(beanName, mbd, bean)
			);
		}

这段代码不是很复杂,但是很多人不是太理解这段代码的作用,而且,这段代码仅从此函数中去理解也很难弄懂其中的含义,我们需要从全局的角度去思考 Spring 的依赖解决办法。

  • earlySingletonExposure:从字面的意思理解就是提早曝光的单例,我们暂不定义它的学名叫什么,我们感兴趣的是有哪些条件影响这个值。

  • mbd.isSingleton():没有太多可以解释的,此 RootBeanDefinition 代表的是否是单例.

  • this.allowCircularReferences:是否允许循环依赖,很抱歉,并没有找到在配置文件中如何配置,但是在 AbstractRefreshableApplicationContext 中提供了设置函数,可以通过硬编码的方式进行设置或者可以通过自定义命名空间进行配置,其中硬编码的方式代码如下。ClassPathXmlApplicationContext bf = new ClassPathxmlApplicationContext (“aspectTest. xml”);bf. setAllowBeanDefinitionoverriding (false);

  • isSingletonCurrentlyInCreation(beanName):该 bean 是否在创建中。在Spring 中,会有个专门的属性默认为 DefaultSingletonBeanRegistry 的 singletonsCurrentlyInCreation 来记录 bean 的加载状态,在 bean 开始创建前会将 beanName 记录在属性中,在 bean 创建结束后会将 beanName 从属性中移除。那么我们跟随代码一路走来可是对这个属性的记录并没有多少印象,这个状态是在哪里记录的呢?不同 scope 的记录位置并不一样,我们以 singleton 为例,在 singleton 下记录属性的函数是在 DefaultSingletonBeanRegistry 类的 public Object getSingleton(String beanName, ObjectFactory singletonFactory) 函数的 beforeSingletonCreation(beanName)afterSingletonCreation(beanName) 中,在这两段函数中分别 this.singletonsCurrentlyInCreation.add(beanName) 与 this.singletonsCurrentlyInCreation.remove(beanName)来进行状态的记录与移除.

经过以上分析我们了解变量 earlySingletonExposure 是否是单例、是否允许循环依赖、是否对应的 bean 正在创建的条件的综合。当这3个条件都满足时会执行 addSingletonFactory 操作,那么加入 SingletonFactory 的作用是什么呢?又是在什么时候调用呢?

我们还是以最简单 AB 循环依赖为例,类A中含有属性类 B,而类B中又会含有属性类 A,那么初始化 beanA 的过程如图5-3所示。

在这里插入图片描述图 5-3 中展示了创建 beanA 的流程,图中我们看到,在创建A 的时候首先会记录类A 所对应的 beanName,并将 beanA 的创建工厂加入缓存中,而在对A的属性填充也就是调用 populate方法的时候又会再一次的对B进行递归创建。同样的,因为在B中同样存在 A 属性,因此在实例化 B 的的 populate 方法中又会再次地初始化 B,也就是图形的最后,调用 getBean(A)。关键是在这里,有心的同学可以去找找这个代码的实现方式,我们之前已经讲过,在这个函数中并不是直接去实例化A,而是先去检测缀存中是否有已经创建好的对应的 bean,或者是否已经创建好的 ObjectFactory,而此时对于 A 的 ObjectFactory 我们早已经创建,所以便不会再去向后执行,而是直接调用 ObiectFactory 去创建 A。这里最关键的是 ObiectFactory 的实现。

	       // 循环依赖-添加到三级缓存。为避免后期循环依赖,可以在' bean初始化完成前'将创建实例的ObjectFactory加入工厂
			addSingletonFactory(beanName, () ->
					// 对 bean 再一次依赖引用,主要应用 SmartInstantiationAware BeanPostProcessor, 其中我们熟知的 AOP 就是在这里将 advice 动态织人 bean 中,若没有则直接返回bean,不做任何处理
					getEarlyBeanReference(beanName, mbd, bean)
			);

在 getEarlyBeanReference 函数中并没有太多的逻辑处理,或者说除了后处理器的调用外没有别的处理工作,根据以上分析,基本可以理清 Spring 处理循环依赖的解决办法,在B中创建依赖 A 时通过 ObiectFactory 提供的实例化方法来中断 A 中的属性填充,使B中持有的A仅仅是刚刚初始化并没有填充任何属性的 A,而这正初始化 A 的步骤还是在最开始创建A 的时候进行的,但是因为A与B中的A 所表示的属性地址是一样的,所以在A 中创建好的属性填充自然可以通过B中的 A获取,这样就解决了循环依赖的问题.

属性注入

doCreateBean()-populateBean

源码

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;
			}
		}

		/** 给 InstantiationAwareBeanPostProcessors 最后一次机会在属性设置前来改变 bean。如:可以用来支持属性注入的类型 */
		// '实例化后'。 一般用的很少。
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    
    
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
    
    
				if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    
    
					return;
				}
			}
		}

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

		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		/* '自动注入'核心代码 。
		   		自动注入只有两种形式:@Bean(autowire = Autowired.BY_NAME)、@Bean(autowire = Autowired.BY_TYPE);
		   		如果只有@Bean,则是NO模型,下面的代码不会走。
		*
		* */
		// 下面这段代码没有进行属性赋值,而是往pvs里面添加东西
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    
    
			// MutablePropertyValues是PropertyValues具体的实现类
			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();
			}
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
    
    
				// 这里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法,会直接给对象中的属性赋值(遍历每一个注入点进行依赖注入)
				// AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
				// @Resource(CommonAnnotationBeanPostProcessor)、 @Autowired(AutowiredAnnotationBeanPostProcessor)注解都会在此处处理。
				PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
    
    
					if (filteredPds == null) {
    
    
						filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
					}
					/** 对所有依赖检查的属性,进行后置处理 */
					// AutowiredAnnotationBeanPostProcessor
					pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
    
    
						return;
					}
				}
				pvs = pvsToUse;
			}
		}
		if (needsDepCheck) {
    
    
			if (filteredPds == null) {
    
    
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

		/* 真正属性赋值的地方 */
		// 如果当前Bean中的BeanDefinition中设置了PropertyValues,那么最终将是PropertyValues中的值,覆盖@Autowired
		if (pvs != null) {
    
    
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

流程分析

在 populateBean 函数中提供了这样的处理流程。
(1) InstantiationAwareBeanPostProcessor 处理器的 postProcessAfterInstantiation 函数的应用,此函数可以控制程序是否继续进行属性填充。
(2)根据注入类型(byName/byType),提取依赖的 bean,并统一存入 PropertyValues 中。
(3)应用 InstantiationAwareBeanPostProcessor 处理器的postProcessPropertyValues 方法,对属性获取完毕填充前对属性的再次处理,典型应用是RequiredAnnotationBeanPostProcessor 类中对属性的验证。
(4) 将所有 PropertyValues 中的属性填充至 BeanWrapper 中。
在上面的步骤中有几个地方是我们比较感兴趣的,它们分别是依赖注入(autowireByName/autowireByType)以及属性填充,那么,接下来进一步分析这几个功能的实现细节。

1. autowireByName

上文提到根据注入类型(byName/byType),提取依赖的 bean,并统一存入 PropertyValues中,那么我们首先了解下 byName 功能是如何实现的。

     protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    
    

		// 当前Bean中能进行自动注入的属性名
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		// 遍历每个属性名,并去获取Bean对象,并设置到pvs中(此处并没有属性赋值 )
		for (String propertyName : propertyNames) {
    
    
			if (containsBean(propertyName)) {
    
    
				Object bean = getBean(propertyName);
				pvs.add(propertyName, bean);
				// 记录一下propertyName对应的Bean被beanName给依赖了
				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");
				}
			}
		}
	}

如果读者之前了解了 autowire 的使用方法,相信理解这个函数的功能不会太困难,无非是在传入的参数 pvs 中找出已经加载的 bean,并递归实例化,进而加人到 pvs中。

2. autowireByType

autowireByType 与 autowireByName 对于我们理解与使用来说复杂程度都很相似,但是其实现功能的复杂度却完全不一样。

protected void autowireByType(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    
    

		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
    
    
			converter = bw;
		}

		Set<String> autowiredBeanNames = new LinkedHashSet<>(4);

		// 当前Bean中能进行自动注入的属性名
		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.
				if (Object.class != pd.getPropertyType()) {
    
    
					MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
					// Do not allow eager init for type matching in case of a prioritized post-processor.
					// eager表示立即初始化,表示在根据类型查找Bean时,允不允许进行Bean的创建,如果当前bean实现了PriorityOrdered,那么则不允许
					// 为什么不允许,因为我自己是PriorityOrdered,是优先级最高的,不能有比我创建得更早的
					boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
					DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
					/** 解析指定 beanName 的属性所匹配的值,并把解析到的属性名称存储在autowiredBeanNames 中,当属性存在多个封装 bean 时如:@Autowired private List<A> alist;将会找到所有匹配A类型的 bean并將其注人*/
					// 根据类型找到的结果
					Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
					if (autowiredArgument != null) {
    
    
						pvs.add(propertyName, autowiredArgument);
					}
					// 注册依赖
					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);
			}
		}
	}

实现根据名称自动匹配的第一步就是寻找 bw 中需要依赖注入的属性,同样对于根据类型自动匹配的实现来讲第一步也是寻找 bw 中需要依赖注人的属性,然后遍历这些属性并寻找类型匹配的 bean,其中最复杂的就是寻找类型匹配的 bean。同时,Spring 中提供了对集合的类型注入的支持,如使用注解的方式:

@Autowired
private List<Test> tests;

Spring 将会把所有与 Test 匹配的类型找出来并注入到 tests 属性中,正是由于这一因素,所以在 autowireByType 函数中,新建了局部遍历 autowiredBeanNames,用于存储所有依赖的bean,如果只是对非集合类的属性注入来说,此属性并无用处。

对于寻找类型匹配的逻辑实现封装在了 resolveDependency 函数中。

private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
    
    

		Class<?> type = descriptor.getDependencyType();

		if (descriptor instanceof StreamDependencyDescriptor) {
    
    
			// 找到type所匹配的所有bean
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (autowiredBeanNames != null) {
    
    
				autowiredBeanNames.addAll(matchingBeans.keySet());
			}

			// 构造成一个stream
			Stream<Object> stream = matchingBeans.keySet().stream()
					.map(name -> descriptor.resolveCandidate(name, type, this))
					.filter(bean -> !(bean instanceof NullBean));

			// 排序
			if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
    
    
				stream = stream.sorted(adaptOrderComparator(matchingBeans));
			}
			return stream;
		}
		else if (type.isArray()) {
    
    
			// 得到数组元素的类型
			Class<?> componentType = type.getComponentType();
			ResolvableType resolvableType = descriptor.getResolvableType();
			Class<?> resolvedArrayType = resolvableType.resolve(type);
			if (resolvedArrayType != type) {
    
    
				componentType = resolvableType.getComponentType().resolve();
			}
			if (componentType == null) {
    
    
				return null;
			}
			/**
			 * 根据属性类型找到 beanFactory 中所有类型的匹配 bean, 返回值的构成为:key-匹配的 beanName, value-beanName 对应的实例化后的 bean(通过getBean (beanName) 返回)
			 */
			// 根据数组元素类型找到所匹配的所有Bean
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
					new MultiElementDescriptor(descriptor));
			if (matchingBeans.isEmpty()) {
    
    
				return null;
			}
			if (autowiredBeanNames != null) {
    
    
				autowiredBeanNames.addAll(matchingBeans.keySet());
			}
			// 进行类型转化
			TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
			Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
			if (result instanceof Object[]) {
    
    
				Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
				if (comparator != null) {
    
    
					Arrays.sort((Object[]) result, comparator);
				}
			}
			return result;
		}
		else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
    
    
			Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
			if (elementType == null) {
    
    
				return null;
			}
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
					new MultiElementDescriptor(descriptor));
			if (matchingBeans.isEmpty()) {
    
    
				return null;
			}
			if (autowiredBeanNames != null) {
    
    
				autowiredBeanNames.addAll(matchingBeans.keySet());
			}
			TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
			Object result = converter.convertIfNecessary(matchingBeans.values(), type);
			if (result instanceof List) {
    
    
				if (((List<?>) result).size() > 1) {
    
    
					Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
					if (comparator != null) {
    
    
						((List<?>) result).sort(comparator);
					}
				}
			}
			return result;
		}
		else if (Map.class == type) {
    
    
			ResolvableType mapType = descriptor.getResolvableType().asMap();
			Class<?> keyType = mapType.resolveGeneric(0);
			// 如果Map的key不是String
			if (String.class != keyType) {
    
    
				return null;
			}
			Class<?> valueType = mapType.resolveGeneric(1);
			if (valueType == null) {
    
    
				return null;
			}
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
					new MultiElementDescriptor(descriptor));
			if (matchingBeans.isEmpty()) {
    
    
				return null;
			}
			if (autowiredBeanNames != null) {
    
    
				autowiredBeanNames.addAll(matchingBeans.keySet());
			}
			return matchingBeans;
		}
		else {
    
    
			return null;
		}
	}

寻找类型的匹配执行顺序时,首先尝试使用解析器进行解析,如果解析器没有成功解析,那么可能是使用默认的解析器没有做任何处理,或者是使用了自定义的解析器,但是对于集合等类型来说并不在解析范围之内,所以再次对不同类型进行不同情况的处理,虽说对于不同类型处理方式不一致,但是大致的思路还是很相似的,所以函数中只对数组类型进行了详细地注释。

3. applyPropertyValues

程序运行到这里,已经完成了对所有注入属性的获取,但是获取的属性是以Property Values形式存在的,还并没有应用到已经实例化的 bean 中,这一工作是在populateBean方法最后 applyPropertyValues 中处理的。

初始化 bean

doCreateBean()-initializeBean

大家应该记得在 bean 配置时 bean 中有一个 init-method 的属性,这个属性的作用是在 bean实例化前调用 init-method 指定的方法来根据用户业务进行相应的实例化。我们现在就已经进入这个方法了,首先看一下这个方法的执行位置,Spring 中程序已经执行过 bean 的实例化,并且进行了属性的填充,而就在这时将会调用用户设定的初始化方法。

源码

	protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    
    
		if (System.getSecurityManager() != null) {
    
    
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    
    
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
    
    
			/** 对特殊的 bean 处理:Aware、 BeanclassLoaderAware、 BeanFactoryAware*/
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;

		if (mbd == null || !mbd.isSynthetic()) {
    
    
			/** 初始化前 */
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
    
    
			/** 初始化。激活用户自动定义的init方法 */
			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()) {
    
    
			/** 初始化后 AOP */
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

虽然说此丽数的主要目的是进行客户设定的初始化方法的调用,但是除此之外还有些其他必要的工作。

1. 激活 Aware 方法

在分析其原理之前,我们先了解一下 Aware 的使用。Spring 中提供一些 Aware 相关接口,比如 BeanFactoryAware、 ApplicationContextAware、 ResourceLoaderAware、 ServleContextAware 等,实现这些 Aware 接口的 bean 在被初始之后,可以取得一些相对应的资源,例如实现Bean Factory Aware 的 bean 在初始后,Spring 容器将会注人 BeanFactory 的实例,而实现ApplicationContextAware 的 bean,在 bean 被初始后,将会被注人 ApplicationContext 的实例等。我们首先通过示例方法来了解一下 Aware 的使用。
在这里插入图片描述
在这里插入图片描述按照上面的方法我们可以获取到 Spring 中 BeanFactory,并且可以根据 BeanFactory 获取所有 bean,以及进行相关设置。当然还有其他 Aware 的使用方法都大同小异,看一下 Spring的实现方式,相信读者便会使用了。

private void invokeAwareMethods(String beanName, Object bean) {
    
    
		if (bean instanceof Aware) {
    
    
			if (bean instanceof BeanNameAware) {
    
    
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
    
    
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
    
    
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
    
    
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

2. 处理器的应用

BeanPostProcessor 相信大家都不陌生,这是 Spring 中开放式架构中一个必不可少的亮点,给用户充足的权限去更改或者扩展 Spring,而除了 BeanPostProcessor 外还有很多其他的PostProcessor,当然大部分都是以此为基础,继承自 BeanPostProcessor。BeanPostProcessor 的使用位置就是这里,在调用客户自定义初始化方法前以及调用自定义初始化方法后分别会调用BeanPostProcessor 的 postProcessBeforelnitialization 和 postProcessA fterInitialization 方法,使用户可以根据自己的业务需求进行响应的处理。

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

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

3. 激活自定义的 init 方法

客户定制的初始化方法除了我们熟知的使用配置 init-method 外,还有使自定义的 bean 实现 InitializingBean 接口,并在 afierPropertiesSet 中实现自己的初始化业务逻辑。
init-method 与 afterPropertiesSet 都是在初始化 bean 时执行,执行顺序是 afterPropertiesSet先执行,而 init-method 后执行。
在 invokelnitMethods 方法中就实现了这两个步骤的初始化方法调用。

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {
    
    

		/** 首先会检查是否是 InitializingBean,如果是的话需要调用 afterPropertiesSet 方法*/
		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
    
    
			if (logger.isTraceEnabled()) {
    
    
				logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			}
			if (System.getSecurityManager() != null) {
    
    
				try {
    
    
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
    
    
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) {
    
    
					throw pae.getException();
				}
			}
			else {
    
    
				/** 属性初始化后的处理*/
				((InitializingBean) bean).afterPropertiesSet();
			}
		}

		if (mbd != null && bean.getClass() != NullBean.class) {
    
    
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
    
    
				/** 调用自定义方法*/
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}

注册 DisposableBean

Spring 中不但提供了对于初始化方法的扩展入口,同样也提供了销毁方法的扩展入口,对于销毁方法的扩展,除了我们熟知的配置屈性 destroy-method 方法外,用户还可以注册后处理器 DestructionAwareBeanPostProcessor 来统一处理 bean 的销毁方法,代码如下:

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
    
    
		AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
		// if(不是'多例'bean && 有销毁方法)。 原型bean即使定义了销毁方法,但是执行不会调用销毁方法。
		if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
    
    
			// 单例bean出来逻辑
			if (mbd.isSingleton()) {
    
    
				/**
				 * 单例模式下注册需要销段的 bean,此方法中会处理实现 DisposableBean 的 bean,
				 * 并且对所有的 bean 使用 DestructionAwareBeanPostProcessors 处理
				 * DisposableBean DestructionAwareBeanPostProcessors,
				 * */
				registerDisposableBean(beanName, new DisposableBeanAdapter(
						bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
			}
			else {
    
    
				/** 自定义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, getBeanPostProcessorCache().destructionAware, acc));
			}
		}
	}

总结

略。

猜你喜欢

转载自blog.csdn.net/qq_43783527/article/details/129341540