Spring Bean的实例化源码解析

Spring Bean的实例化源码解析,第1张

目录
  • createBeanInstance
  • 实例化Bean的方式
    • 回调函数实例化Bean
      • 配置回调函数的示例
    • 工厂方法实例化Bean
      • 参数解析
      • 参数类型转换
      • 执行工厂方法,实例化Bean
    • 指定构造函数实例化Bean
      • 参数解析和参数类型转换
      • 执行构造函数,实例化Bean
    • 默认无参构造函数实例化Bean

说明:我的源码是 v5.2.4.RELEASE 版本,因为几年前看过,有一些相关的注释在上面,所以就没有拉取最新的源码,有可能最新的代码与这个版本有一些差异,但是整体思路应该不差多吧。

实例化是Bean生命周期的第一步,关于Bean生命周期及其源码可以参考 Spring Bean的生命周期 。
Spring实例化Bean的入口是AbstractAutowireCapableBeanFactory.createBeanInstance(),该方法在AbstractAutowireCapableBeanFactory.doCreateBean()中被调用。doCreateBean方法的部分源码如下:

// AbstractAutowireCapableBeanFactory
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
		throws BeanCreationException {
	// Instantiate the bean.
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); // 从FactoryBean缓存列表中移除
	}
	/*
	 * 第一步:实例化Bean。
	 * 使用合适的实例化策略来实例化新的Bean:回调函数、工厂方法、带参的构造函数、无参构造函数。默认调用无参构造器实例化Bean。
	 * 构造函数自动注入发生在这一步
	 */
	if (instanceWrapper == null) { // 为null,说明不是FactoryBean,那么调用工厂或者构造函数实例化Bean
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	// 省略掉大量代码,这些代码用于初始化Bean、属性赋值、循环依赖处理等
	return exposedObject;
}
createBeanInstance
// AbstractAutowireCapableBeanFactory
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
	// Make sure bean class is actually resolved at this point.
	// 从bean定义中解析出当前bean的class对象
	Class<?> beanClass = resolveBeanClass(mbd, beanName);

	// 检测类的访问权限。对于非public类,默认是允许访问的;若被设置为禁止访问非public的类,则这里会抛出异常
	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());
	}

	/*
	 * 这是Spring5提供的一种替换工厂方法的方式,提供一个回调函数实例化Bean
	 * 自己创建BeanDefinition对象,然后注册到IoC容器中时,有可能使用到这种方式
	 */
	Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
	if (instanceSupplier != null) {
	    // 这里的代码很简单,就是执行回调函数获取Bean的实例
		return obtainFromSupplier(instanceSupplier, beanName);
	}

	/*
	 * 判断是不是使用工厂实例化Bean,工厂方法名称不为空,即表示使用工厂方法进行实例化。
	 * 无论是静态工厂还是实例工厂,都是走这一步
	 * 通过Java配置类配置的Bean,实例化方式采用的是实例工厂方法,工厂实例就是Java配置类的代理对象
	 */
	if (mbd.getFactoryMethodName() != null) {
		return instantiateUsingFactoryMethod(beanName, mbd, args);
	}

	// Shortcut when re-creating the same bean...
	boolean resolved = false; // 判断Bean定义中的构造函数或者工厂方法是否已被解析过
	boolean autowireNecessary = false; // 有没有必要进行依赖注入
	if (args == null) { // getBean方法传入的参数为null
		synchronized (mbd.constructorArgumentLock) {
			/*
			 * 判断bean定义中的resolvedConstructorOrFactoryMethod属性是否有值
			 * 该属性用来缓存构造函数或者工厂方法,Bean在第一次被实例化的时候,会将解析得到的构造函数或者工厂方法赋值给这个属性
			 * 对于非单例模式的Bean来说,只需要解析一次Bean定义中的构造函数或工厂方法即可,后续可以直接从Bean定义中拿来使用
			 */
			if (mbd.resolvedConstructorOrFactoryMethod != null) {
				resolved = true; // 标记构造函数已被解析过了,原型等非单例模式的Bean,从第二次实例化开始就会进入这里
				// 构造函数参数是否被解析过?当使用有参构造函数或者工厂方法实例化Bean时,该属性会被设置为true
				autowireNecessary = mbd.constructorArgumentsResolved;
			}
		}
	}
	if (resolved) { // 已经解析过了,直接实例化Bean即可
		if (autowireNecessary) {
			// 使用有参构造函数实例化对象
			return autowireConstructor(beanName, mbd, null, null);
		}
		else {
			// 使用无参构造函数实例化对象
			return instantiateBean(beanName, mbd);
		}
	}

	// Candidate constructors for autowiring?
	/*
	 * 调用Bean后置处理器(AutowiredAnnotationBeanPostProcessor),获取用于实例化Bean的构造函数
	 * 如果有多个构造函数,构造函数上都有@Autowired注解,无论required属性为何值,都会抛出异常,如果仅有一个构造函数有注解,则使用这个
	 * 如果只有xml配置,这里一般都是返回null
	 */
	Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
	/*
	 * 1. 上一行后置处理器解析出的构造函数不为null
	 * 2. bean定义中指定自动注入模式是构造器注入
	 *     这种方式定义的Bean即是构造函数自动注入
	 *    在构造函数上使用了@Autowire注解,也是构造函数自动注入
	 *    通过Java配置类定义的Bean,无论方法参数是否有值,都会被解析为构造函数自动注入
	 *    在Bean定义时,显示指定了构造函数参数(constructor-arg),则不是构造函数自动注入(注意,这里指的自动注入模式)
	 *    静态工厂和实例工厂定义的Bean,不是构造函数自动注入
	 * 3. bean定义中指定了构造函数,无论参数是通过名称、类型、下标配置,都是走这一步
	 * 4. 在外层,调用getBean方法传入的构造器函数参数类型不为null
	 * 四个条件有一个满足,就使用指定的构造函数进行实例化Bean
	 */
	if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
			mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
		// 使用指定的构造函数实例化对象,构造函数自动注入在这里完成
		return autowireConstructor(beanName, mbd, ctors, args);
	}

	// Preferred constructors for default construction?
	/*
	 * bean定义中的首选构造器
	 * 目前只有 GenericApplicationContext#ClassDerivedBeanDefinition类的这个方法有返回值,其它都是返回null
	 * 所以,Bean的实例化,基本不会走这一步
	 */
	ctors = mbd.getPreferredConstructors();
	if (ctors != null) {
		// 实例化Bean
		return autowireConstructor(beanName, mbd, ctors, null);
	}

	// No special handling: simply use no-arg constructor.
	// 如果前面的条件都不匹配,则使用无参构造函数实例化对象
	return instantiateBean(beanName, mbd);
}

从上面的源码可以看出,Spring提供了三种实例化Bean的方式:

  1. Supplier回调函数。这是从Spring5开始提供的一种实例化方式。通过工厂、构造函数实例化对象时,Spring使用的都是反射,而反射的性能相对较差。Supplier回调函数可以自定义实例化过程,无须通过反射调用,直接执行函数即可。
  2. 工厂方法。又分为静态工厂和实例工厂。
  3. 构造函数。有参构造函数、无参构造函数。当没有配置使用哪个构造函数时,默认使用无参构造函数实例化。

还有一种实例化方式是FactoryBean,例如Spring Cloud中实例化FeignClient对象,使用的是FeignClientFactoryBean。这种方式的流程相对长一些、麻烦一些,这篇文档没有对这种方式进行分析。

在Java配置类中配置的Bean,使用的是实例工厂实例化,实例工厂是Java配置类的代理对象,这个代理对象是在Spring解析Java配置类时创建的。

对于非单例模式的Bean,Spring做了一些性能优化,只有第一次实例化Bean时,才需要解析Bean定义的构造函数、工厂方法、参数值等,解析完成之后会将这些数据回写到Bean定义对象的对应属性。下次再创建时,直接从Bean定义中获取即可,无须再次解析。

实例化Bean的方式 回调函数实例化Bean

通过回调函数实例化Bean的代码非常简单,直接执行Bean定义中的回调函数,无须解析参数,也不需要进行反射调用。源码如下:

// AbstractAutowireCapableBeanFactory
protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
	Object instance;

	// 设置当前正在实例化的Bean的名称到ThreadLocal
	String outerBean = this.currentlyCreatedBean.get();
	this.currentlyCreatedBean.set(beanName);
	try {
		instance = instanceSupplier.get(); // 调用函数,拿到Bean实例
	}
	finally {
		// 重置ThreadLocal
		if (outerBean != null) {
			this.currentlyCreatedBean.set(outerBean);
		}
		else {
			this.currentlyCreatedBean.remove();
		}
	}

	if (instance == null) {
		instance = new NullBean();
	}

	// BeanWrapper接口提供了一些 *** 作目标对象属性值的方法
	BeanWrapper bw = new BeanWrapperImpl(instance);
	initBeanWrapper(bw);
	return bw;
}
配置回调函数的示例

提供一个简单的回调函数配置示例

public class MemberRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		RootBeanDefinition bd = new RootBeanDefinition();
		bd.setBeanClass(Member.class);
		bd.setInstanceSupplier(Member::new); // 这里注册一个回调函数
		registry.registerBeanDefinition("member", bd);
	}

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
	}
}
工厂方法实例化Bean

使用工厂方法实例化Bean的主要代码在ConstructorResolver.instantiateUsingFactoryMethod()方法中,AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod()方法仅仅只有一行代码。具体源码如下:

// AbstractAutowireCapableBeanFactory
protected BeanWrapper instantiateUsingFactoryMethod(
	String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {

return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
// ConstructorResolver
public BeanWrapper instantiateUsingFactoryMethod(
		String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {

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

	// 实例工厂Bean对象,如果是静态工厂,值为null
	Object factoryBean;
	// 工厂的类型
	Class<?> factoryClass;
	// 是否静态工厂
	boolean isStatic;

	// 实例工厂的BeanName,如果是静态工厂,则值为null
	String factoryBeanName = mbd.getFactoryBeanName();
	if (factoryBeanName != null) {
		// 如果是实例工厂,进入这个分支
		// 实例工厂的Bean名称和需要使用工厂实例化的Bean对象的名称相同,则抛出异常
		if (factoryBeanName.equals(beanName)) {
			throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
					"factory-bean reference points back to the same bean definition");
		}
		// 从IoC容器中获取实例工厂对象
		factoryBean = this.beanFactory.getBean(factoryBeanName);
		// 单例Bean,并且在IoC容器的一级缓存中已存在,说明这个Bean已经被创建过了,不能再次创建,抛出异常
		if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
			throw new ImplicitlyAppearedSingletonException();
		}
		factoryClass = factoryBean.getClass(); // 实例工厂的类名,这里可能得到CGLIB生成的子类名称
		isStatic = false;
	}
	else {
		// It's a static factory method on the bean class.
		// 如果是静态工厂,则进入这个分支
		if (!mbd.hasBeanClass()) {
			throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
					"bean definition declares neither a bean class nor a factory-bean reference");
		}
		factoryBean = null;
		factoryClass = mbd.getBeanClass(); // 静态工厂的类名
		isStatic = true;
	}

	Method factoryMethodToUse = null; // 用于实例化Bean的工厂方法
	ArgumentsHolder argsHolderToUse = null; // 持有 用于实例化Bean的参数 对象
	Object[] argsToUse = null; // 用于实例化Bean的参数

	if (explicitArgs != null) {
		argsToUse = explicitArgs;
	}
	else {
		Object[] argsToResolve = null;
		synchronized (mbd.constructorArgumentLock) {
			/*
			 * 工厂方法是否已经被解析过
			 * 第一次实例化Bean时,解析Bean定义,找到实例化Bean的工厂方法,
			 * 然后会将工厂方法回写到Bean定义中的resolvedConstructorOrFactoryMethod属性,并且constructorArgumentsResolved属性也会被设置为true。
			 * 当下次再需要实例化这个Bean时,就无须再次解析,直接从Bean定义中获取即可,这是对非单例作用域的Bean实例化过程的优化
			 */
			factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
			if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
				// Found a cached factory method...
				argsToUse = mbd.resolvedConstructorArguments;
				if (argsToUse == null) {
					argsToResolve = mbd.preparedConstructorArguments;
				}
			}
		}
		if (argsToResolve != null) {
			argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
		}
	}

	if (factoryMethodToUse == null || argsToUse == null) {
		// Need to determine the factory method...
		// Try all methods with this name to see if they match the given arguments.
		// 获取工厂的实际类型,如果是CGLIB生成的子类,则返回原始类;否则返回的就是参数值
		factoryClass = ClassUtils.getUserClass(factoryClass);

		List<Method> candidates = null; // 可用于实例化Bean的工厂方法
		if (mbd.isFactoryMethodUnique) { // 如果是宰Java配置类中配置的Bean,会走这块代码
			if (factoryMethodToUse == null) {
				factoryMethodToUse = mbd.getResolvedFactoryMethod();
			}
			if (factoryMethodToUse != null) {
				candidates = Collections.singletonList(factoryMethodToUse);
			}
		}
		if (candidates == null) { // 如果是静态工厂或者实例工厂,会走块代码
			candidates = new ArrayList<>();
			Method[] rawCandidates = getCandidateMethods(factoryClass, mbd); // 获取工厂类的所有方法
			/*
			 * 遍历工厂的所有方法,找出实例化Bean的方法,
			 * 如果是静态工厂,则方法必须是静态的,且方法名称与Bean定义中的相同;
			 * 如果是实例工厂,则方法不能是静态的,且方法名称与Bean定义中的相同。
			 */
			for (Method candidate : rawCandidates) {
				if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
					candidates.add(candidate);
				}
			}
		}

		/*
		 * 只有一个符合条件的工厂方法,并且方法没有显示配置参数(工厂方法显示配置参数使用的是构造函数参数标签 constructor-arg)
		 * 关于Java配置类中定义的Bean的规则说明:
		 *     无论方法上有没有参数,
		 *     参数是否使用了@Autowired注解,
		 *     还是方法内部调用了其它生成Bean的方法,
		 *     实例化Bean的构造函数是否有参,
		 * 其在Bean定义中都是没有构造参数/方法的。
		 */
		if (candidates.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
			Method uniqueCandidate = candidates.get(0); // 唯一可以用来实例化Bean的工厂方法
			if (uniqueCandidate.getParameterCount() == 0) { // 方法的参数个数为0,这里指的是方法实际的参数,而不是显示配置的参数
				mbd.factoryMethodToIntrospect = uniqueCandidate;
				synchronized (mbd.constructorArgumentLock) {
					/*
					 * 将用于实例化Bean的工厂方法回写到Bean定义的resolvedConstructorOrFactoryMethod属性
					 * 设置构造函数参数(方法参数)已解析标识为true
					 * 回写构造函数或工厂方法参数
					 * 后续如果需要再次实例化Bean,则无需解析。
					 * 这是对非单例模式Bean实例化的优化手段,只需要第一次实例化时解析,后续实例化Bean就可以直接从Bean定义中拿来用
					 */
					mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
					mbd.constructorArgumentsResolved = true;
					mbd.resolvedConstructorArguments = EMPTY_ARGS;
				}

				// 通过反射的方式执行工厂方法实例化Bean,Method.invoke()
				bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
				return bw;
			}
		}

		/*
		 * 扎到多个名字相同的工厂方法,则先进行排序,排序规则如下:
		 * 先根据限定符(public\private等)进行排序,public排在最前面,
		 * 限定符相同,则再根据方法参数数量进行排序,参数多的排在前面
		 */
		if (candidates.size() > 1) {  // explicitly skip immutable singletonList
			candidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR);
		}

		/*
		 * 用于保存方法参数值的对象
		 * 如果是通过索引配置的参数,则使用一个Map保存参数,key是下标值,value是参数值
		 * 如果是类型、参数名称等其他配置方式,则使用一各List保存参数
		 */
		ConstructorArgumentValues resolvedValues = null;
		/*
		 * 是否是构造函数自动注入
		 * 通过Java配置类定义的Bean,无论方法参数是否有值,都会被认为是构造函数自动注入
		 * 静态工厂和实例工厂定义的Bean,不是构造函数注入
		 */
		boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
		int minTypeDiffWeight = Integer.MAX_VALUE;
		Set<Method> ambiguousFactoryMethods = null;

		int minNrOfArgs; // 方法最小的参数数量
		if (explicitArgs != null) {
			minNrOfArgs = explicitArgs.length;
		}
		else {
			// We don't have arguments passed in programmatically, so we need to resolve the
			// arguments specified in the constructor arguments held in the bean definition.
			if (mbd.hasConstructorArgumentValues()) { // 是否显示配置了参数
				// 获取Bean定义中的参数信息,例如有多少个参数,参数是什么类型、名称等,就是Bean定义的参数信息
				ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
				resolvedValues = new ConstructorArgumentValues();
				/*
				 * 解析方法的参数值,如果在方法的配置中指定的其它Bean还没有创建,此处会将需要的Bean创建出来。
				 * 通过索引配置的参数是单独一种解析方法,解析的结果保存在一个Map中,key是索引,value是值对象。
				 * 通过默认(只配置了值)、类型、名称配置的参数是同一种解析方法,解析结果保存在一个List中。
				 * 通过构造器注入,没有显示配置参数时,这一段代码什么都不做。
				 * 返回值是配置的参数数量,方法的参数数量必须大于等于这个值。
				 */
				minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
			}
			else {
				minNrOfArgs = 0;
			}
		}

		// 解析方法参数过程中出现的异常,方法可能被重载,当被解析的方法与Bean定义中的方法无法匹配时,就会抛出异常
		LinkedList<UnsatisfiedDependencyException> causes = null;

		for (Method candidate : candidates) {

			int parameterCount = candidate.getParameterCount(); // 方法的参数数量
			if (parameterCount >= minNrOfArgs) { // 方法的参数数量必须大于等于配置的参数数量
				ArgumentsHolder argsHolder;

				Class<?>[] paramTypes = candidate.getParameterTypes(); // 方法的参数类型
				if (explicitArgs != null) { // explicitArgs是调用getBean方式时传入的参数
					// Explicit arguments given -> arguments length must match exactly.
					if (paramTypes.length != explicitArgs.length) {
						continue;
					}
					argsHolder = new ArgumentsHolder(explicitArgs);
				}
				else {
					// Resolved constructor arguments: type conversion and/or autowiring necessary.
					try {
						String[] paramNames = null; // 方法参数的名称
						ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
						if (pnd != null) {
							paramNames = pnd.getParameterNames(candidate); // 解析方法参数的名称
						}
						/*
						 * 解析方法的参数,这里会找出方法依赖的Bean
						 * 配置的参数与方法需要的参数是否匹配,如果不匹配,会抛出异常,然后再解析下一个方法,如果所有的方法都不匹配,才会向外层抛出异常
						 */
						argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
								paramTypes, paramNames, candidate, autowiring, candidates.size() == 1);
					}
					catch (UnsatisfiedDependencyException ex) { // 出现异常时,先缓存起来
						if (logger.isTraceEnabled()) {
							logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
						}
						// Swallow and try next overloaded factory method.
						if (causes == null) {
							causes = new LinkedList<>();
						}
						causes.add(ex);
						continue;
					}
				}

				/*
				 * 根据宽松模式还是严格模式,使用不同的方法计算参数值类型与方法参数类型之间的差异。
				 * 值类型与参数类型之间的差异越小(计算结果越小),优先级越高。
				 * 例如对于 Integer 类型的参数,构造函数 (Integer) 将优于构造函数 (Number),而后者又将优于构造函数 (Object)
				 */
				int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
						argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
				// Choose this factory method if it represents the closest match.
				if (typeDiffWeight < minTypeDiffWeight) { // 使用优先级更高的方法
					factoryMethodToUse = candidate; // 实例化Bean的工厂方法
					argsHolderToUse = argsHolder; // 持有工厂方法参数的对象
					argsToUse = argsHolder.arguments; // 工厂方法需要的参数
					minTypeDiffWeight = typeDiffWeight;
					ambiguousFactoryMethods = null;
				}
				// Find out about ambiguity: In case of the same type difference weight
				// for methods with the same number of parameters, collect such candidates
				// and eventually raise an ambiguity exception.
				// However, only perform that check in non-lenient constructor resolution mode,
				// and explicitly ignore overridden methods (with the same parameter signature).
				// 添加到模糊工厂方法列表,如果是严格模式,且又找到多个匹配的工厂方法,则会抛出异常。默认是宽松模式
				else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
						!mbd.isLenientConstructorResolution() &&
						paramTypes.length == factoryMethodToUse.getParameterCount() &&
						!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
					if (ambiguousFactoryMethods == null) {
						ambiguousFactoryMethods = new LinkedHashSet<>();
						ambiguousFactoryMethods.add(factoryMethodToUse);
					}
					ambiguousFactoryMethods.add(candidate);
				}
			}
		}

		// 找不到与Bean定义匹配的方法,则抛出异常
		if (factoryMethodToUse == null || argsToUse == null) {
			if (causes != null) {
				UnsatisfiedDependencyException ex = causes.removeLast();
				for (Exception cause : causes) {
					this.beanFactory.onSuppressedException(cause);
				}
				throw ex;
			}
			List<String> argTypes = new ArrayList<>(minNrOfArgs);
			if (explicitArgs != null) {
				for (Object arg : explicitArgs) {
					argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
				}
			}
			else if (resolvedValues != null) {
				Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
				valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
				valueHolders.addAll(resolvedValues.getGenericArgumentValues());
				for (ValueHolder value : valueHolders) {
					String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
							(value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
					argTypes.add(argType);
				}
			}
			String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"No matching factory method found: " +
					(mbd.getFactoryBeanName() != null ?
						"factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
					"factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
					"Check that a method with the specified name " +
					(minNrOfArgs > 0 ? "and arguments " : "") +
					"exists and that it is " +
					(isStatic ? "static" : "non-static") + ".");
		}
		// 如果工厂方法的返回值是void,则抛出异常
		else if (void.class == factoryMethodToUse.getReturnType()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Invalid factory method '" + mbd.getFactoryMethodName() +
					"': needs to have a non-void return type!");
		}
		// 严格解析模式,找到了多个模糊匹配的方法,则抛出异常
		else if (ambiguousFactoryMethods != null) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Ambiguous factory method matches found in bean '" + beanName + "' " +
					"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
					ambiguousFactoryMethods);
		}

		if (explicitArgs == null && argsHolderToUse != null) {
			mbd.factoryMethodToIntrospect = factoryMethodToUse; // 回写工厂方法到Bean定义的属性
			// 回写相关信息到Bean定义中,例如上面提到的resolvedConstructorOrFactoryMethod、constructorArgumentsResolved等属性
			argsHolderToUse.storeCache(mbd, factoryMethodToUse);
		}
	}

	// 通过反射实例化Bean,Method.invoke()
	bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
	return bw;
}

使用工厂方法实例化Bean,主要有如下几个步骤:

  1. 如果是实例工厂,则先获取实例工厂对象。
  2. 找出可用于实例化Bean的方法,方法可能被重载,那么就会找到多个,此时需要根据方法的参数进行匹配查找。
  3. 解析配置的参数值,根据索引、类型、名称等解析出配置的方法参数,如果是一个Bean,又还没有创建,则此处会创建这个Bean。
  4. 将参数值与方法实际参数类型做匹配,找出最终用于实例化的方法,如果找不到,则实例化失败。
  5. 将方法、参数等数据回写到Bean定义对象的相关属性上,再次创建相同的Bean时,就无需解析,直接从Bean定义中取即可。
  6. 使用反射的方式执行方法Method.invoke(),实例化Bean。
参数解析

工厂方法参数和构造函数参数的解析都是这个方法。

// ConstructorResolver
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
		ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {

	TypeConverter customConverter = this.beanFactory.getCustomTypeConverter(); // 自定义的参数类型解析器,默认为null
	TypeConverter converter = (customConverter != null ? customConverter : bw); // 如果没有自定义,使用BeanWrapper
	BeanDefinitionValueResolver valueResolver =
			new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter); // Bean定义值解析器

	int minNrOfArgs = cargs.getArgumentCount(); // 参数的数量

	// 通过索引位置配置的参数,走这里
	for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
		int index = entry.getKey(); // 索引
		if (index < 0) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Invalid constructor argument index: " + index);
		}
		if (index > minNrOfArgs) {
			minNrOfArgs = index + 1;
		}
		ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue(); // 参数值
		if (valueHolder.isConverted()) { // 参数值是否已经转换,例如参数引用了一个Bean,这个Bean是否已经被创建出来
			resolvedValues.addIndexedArgumentValue(index, valueHolder); // 回写方法参数
		}
		else {
			// 参数转换后的值,例如参数是一个Bean,则此处会将Bean创建出来,如果Bean已经创建了,则直接从IoC容器中拿到这个Bean。
			Object resolvedValue =
					valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
			// 保存参数值的对象
			ConstructorArgumentValues.ValueHolder resolvedValueHolder =
					new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
			resolvedValueHolder.setSource(valueHolder);
			// 回写方法参数值,索引是key,value是参数值
			resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
		}
	}

	// 默认、类型、名称配置的参数,走这里
	for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
		if (valueHolder.isConverted()) {
			resolvedValues.addGenericArgumentValue(valueHolder);
		}
		else {
			// 参数值解析,如果引用了其它Bean,这里会将Bean创建出来
			Object resolvedValue =
					valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
			ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(
					resolvedValue, valueHolder.getType(), valueHolder.getName()); // 保存参数值的对象
			resolvedValueHolder.setSource(valueHolder);
			// 回写方法参数值,保存在一个list中
			resolvedValues.addGenericArgumentValue(resolvedValueHolder);
		}
	}

	return minNrOfArgs;
}

定义Bean时,配置方法需要的参数,可以仅设值(默认),也可以使用索引位置、参数类型、参数名称多种方式配置。

  • 通过索引位置配置的参数,有独立的解析方式,解析结果保存在一个Map中,key是索引位置,value是值对象。
  • 其它方式配置的参数,解析方式是一样的,解析结果保存在一个List中。

注意:如果我们在定义Bean时,没有显示的配置参数,则参数不会在这里解析,这个方法相当于什么事都没做,这种情况下 ConstructorArgumentValues resolvedValues中的Map和List都是空。

参数类型转换

上一步解析得到的参数值,其类型并不一定与方法的参数类型匹配,所以需要对参数值做一次类型转换,转换失败则说明不能使用这个方法。
什么情况下会转换失败?
当通过索引、名称进行配置时,得到的参数值的类型就有可能与实际需要的参数类型不匹配,此时就会转换失败,抛出异常。

// ConstructorResolver
private ArgumentsHolder createArgumentArray(
		String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,
		BeanWrapper bw, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable,
		boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException {

	// 自定义的类型转换器,如果没有自定义,则为null
	TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
	// 如果没有自定义类型转换器,则使用BeanWrapper对象
	TypeConverter converter = (customConverter != null ? customConverter : bw);

	ArgumentsHolder args = new ArgumentsHolder(paramTypes.length); // 用于保存参数值的对象
	Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length); // 用于保存参数值的集合
	Set<String> autowiredBeanNames = new LinkedHashSet<>(4); // 注入的Bean名称集合,用于注册依赖关系

	for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) { // 遍历方法/构造函数的参数类型
		// 当前索引位置的参数类型(方法/构造函数上的参数类型)
		Class<?> paramType = paramTypes[paramIndex];
		// 当前索引位置的参数名称(方法/构造函数上的参数名称)
		String paramName = (paramNames != null ? paramNames[paramIndex] : "");
		// Try to find matching constructor argument value, either indexed or generic.
		ConstructorArgumentValues.ValueHolder valueHolder = null; // 参数值
		// resolvedValues保存的是已经转换过的、显示配置的参数值。如果是构造器自动注入,这个对象中是没有值的
		if (resolvedValues != null) {
			// 根据Bean定义配置,通过参数索引 -> 参数名称 -> 参数类型 查找参数值
			// 如果是构造函数注入,则这里返回的是null
			valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
			// If we couldn't find a direct match and are not supposed to autowire,
			// let's try the next generic, untyped argument value as fallback:
			// it could match after type conversion (for example, String -> int).
			// 如果我们找不到直接匹配并且不是自动装配,让我们尝试下一个通用的、无类型的参数值作为后备:它可以在类型转换后匹配(例如,String -> int)。
			if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
				valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
			}
		}
		if (valueHolder != null) { // 构造函数注入时,valueHolder为null,所以不会走这个分支
			// We found a potential match - let's give it a try.
			// Do not consider the same value definition multiple times!
			// 找到了参数值,则尝试将值转成方法/构造函数需要的类型。
			usedValueHolders.add(valueHolder);
			Object originalValue = valueHolder.getValue(); // 参数转换前的值
			Object convertedValue; // 参数转换后的值
			if (valueHolder.isConverted()) { // 参数值是否已经转换过了,则无需再次转换
				convertedValue = valueHolder.getConvertedValue();
				args.preparedArguments[paramIndex] = convertedValue;
			}
			else {
				MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex); // 方法的参数信息
				try {
					/*
					 * 参数类型转换,将参数值转换成构造函数上的参数类型,如果无法转换,则抛出异常。
					 * 当通过索引、名称等方式配置是,可能会转换失败
					 * BeanWrapperImpl.convertIfNecessary,实际调用的是父类TypeConverterSupport.convertIfNecessary,
					 * 而真正的转换是TypeConverterDelegate.convertIfNecessary完成的,
					 * 例如需要一个数组,就创建一个数组,将值放入数组中返回,String换枚举,数字之间的转换等等,
					 * 这个方法的代码相对比较简单,就不列出来了
					 */
					convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
				}
				catch (TypeMismatchException ex) { // 参数值在转换类型是出现了异常
					throw new UnsatisfiedDependencyException(
							mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
							"Could not convert argument value of type [" +
									ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
									"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
				}
				Object sourceHolder = valueHolder.getSource();
				if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) {
					Object sourceValue = ((ConstructorArgumentValues.ValueHolder) sourceHolder).getValue();
					args.resolveNecessary = true;
					args.preparedArguments[paramIndex] = sourceValue;
				}
			}
			args.arguments[paramIndex] = convertedValue;
			args.rawArguments[paramIndex] = originalValue;
		}
		else { // 进入这一步,说明是构造函数自动注入
			MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex); // 方法参数信息
			// No explicit match found: we're either supposed to autowire or
			// have to fail creating an argument array for the given constructor. 
			// 不是构造函数自动注入,则抛出异常
			if (!autowiring) {
				throw new UnsatisfiedDependencyException(
						mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
						"Ambiguous argument values for parameter of type [" + paramType.getName() +
						"] - did you specify the correct bean references as arguments?");
			}
			try {
				// 解析自动注入参数,如果依赖的Bean还没有被创建,此处会进行创建BeanFactory.getBean()
				Object autowiredArgument = resolveAutowiredArgument(
						methodParam, beanName, autowiredBeanNames, converter, fallback);
				args.rawArguments[paramIndex] = autowiredArgument;
				args.arguments[paramIndex] = autowiredArgument;
				args.preparedArguments[paramIndex] = autowiredArgumentMarker;
				args.resolveNecessary = true;
			}
			catch (BeansException ex) {
				throw new UnsatisfiedDependencyException(
						mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
			}
		}
	}

	for (String autowiredBeanName : autowiredBeanNames) {
		this.beanFactory.registerDependentBean(autowiredBeanName, beanName); // 注册Bean之间的依赖关系
		if (logger.isDebugEnabled()) {
			logger.debug("Autowiring by type from bean name '" + beanName +
					"' via " + (executable instanceof Constructor ? "constructor" : "factory method") +
					" to bean named '" + autowiredBeanName + "'");
		}
	}

	return args;
}

参数转换的过程还是相对比较简单的:

  • 首先,以下标的方式变量参数类型。这样就能得到当前方法参数的索引、类型、名称,这样无论是通过哪种方式显示配置的参数,都能获取到参数值。
  • 然后,获取配置的参数值,首先通过下标获取(Map的key),下标获取不到,则通过名称匹配,类型匹配。
  • 最后,将找到的参数值转换成方法需要的类型,这里就可能转换失败了。

获取参数值的源码如下:

// ConstructorArgumentValues
public ValueHolder getArgumentValue(int index, @Nullable Class<?> requiredType, @Nullable String requiredName, @Nullable Set<ValueHolder> usedValueHolders) {
	Assert.isTrue(index >= 0, "Index must not be negative");
	/*
	 * 通过索引从Map(indexedArgumentValues)中获取参数值
	 * 如果还配置了类型,则参数值的类型必须与 requiredType 匹配;没有配置在无须比对
	 * 如果还配置了名称,则参数值的名称必须与 requiredName 匹配;没有配置在无须比对
	 */
	ValueHolder valueHolder = getIndexedArgumentValue(index, requiredType, requiredName);
	// 通过索引获取不到参数值,则遍历 genericArgumentValues 集合,逐个匹配,先匹配参数名称 -> 再匹配参数类型
	if (valueHolder == null) {
		valueHolder = getGenericArgumentValue(requiredType, requiredName, usedValueHolders);
	}
	return valueHolder;
}

// 通过索引取值
public ValueHolder getIndexedArgumentValue(int index, @Nullable Class<?> requiredType, @Nullable String requiredName) {
	Assert.isTrue(index >= 0, "Index must not be negative");
	ValueHolder valueHolder = this.indexedArgumentValues.get(index);
	if (valueHolder != null &&
			(valueHolder.getType() == null ||
					(requiredType != null && ClassUtils.matchesTypeName(requiredType, valueHolder.getType()))) &&
			(valueHolder.getName() == null || "".equals(requiredName) ||
					(requiredName != null && requiredName.equals(valueHolder.getName())))) {
		return valueHolder;
	}
	return null;
}

// 通过名称、类型取值
public ValueHolder getGenericArgumentValue(@Nullable Class<?> requiredType, @Nullable String requiredName, @Nullable Set<ValueHolder> usedValueHolders) {
	for (ValueHolder valueHolder : this.genericArgumentValues) {
		if (usedValueHolders != null && usedValueHolders.contains(valueHolder)) {
			continue;
		}
		// 如果配置了名称,则名称必须与 requiredName 匹配
		if (valueHolder.getName() != null && !"".equals(requiredName) &&
				(requiredName == null || !valueHolder.getName().equals(requiredName))) {
			continue;
		}
		// 如果配置了类型,则类型必须与 requiredType 匹配
		if (valueHolder.getType() != null &&
				(requiredType == null || !ClassUtils.matchesTypeName(requiredType, valueHolder.getType()))) {
			continue;
		}
		// 配置中的类型为空,名称为空(默认 ),则判断参数类型与 requiredType 是否匹配
		if (requiredType != null && valueHolder.getType() == null && valueHolder.getName() == null &&
				!ClassUtils.isAssignableValue(requiredType, valueHolder.getValue())) {
			continue;
		}
		return valueHolder;
	}
	return null;
}
执行工厂方法,实例化Bean
// ConstructorResolver
private Object instantiate(String beanName, RootBeanDefinition mbd,
		@Nullable Object factoryBean, Method factoryMethod, Object[] args) {

	try {
		if (System.getSecurityManager() != null) {
			return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
					this.beanFactory.getInstantiationStrategy().instantiate(
							mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args),
					this.beanFactory.getAccessControlContext());
		}
		else {
			// 通过反射的方式执行工厂方法(Method.invoke())实例化Bean
			return this.beanFactory.getInstantiationStrategy().instantiate(
					mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
		}
	}
	catch (Throwable ex) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
				"Bean instantiation via factory method failed", ex);
	}
}
// SimpleInstantiationStrategy
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
		@Nullable Object factoryBean, final Method factoryMethod, Object... args) {

	try {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				ReflectionUtils.makeAccessible(factoryMethod);
				return null;
			});
		}
		else {
		    // 设置工厂方法的访问属性为 true
			ReflectionUtils.makeAccessible(factoryMethod);
		}

		Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
		try {
		    // 将当前工厂方法存入ThreadLocal对象
			currentlyInvokedFactoryMethod.set(factoryMethod);
			// 通过反射执行工厂方法,实例化Bean
			Object result = factoryMethod.invoke(factoryBean, args);
			if (result == null) {
				result = new NullBean();
			}
			return result;
		}
		finally {
			// ThreadLocal中的值重置
			if (priorInvokedFactoryMethod != null) {
				currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
			}
			else {
				currentlyInvokedFactoryMethod.remove();
			}
		}
	}
	// 异常处理代码,省略......
}

别看代码有这么多,实际实例化Bean的就一行代码:通过反射的方式执行工厂方法factoryMethod.invoke(factoryBean, args),实例化Bean。

指定构造函数实例化Bean

使用构造函数实例化Bean的代码结构、处理步骤,与工厂方法实例化Bean极为相似。

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

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

	/*
	 * 用于实例化Bean的构造函数
	 * 如果有多个符合条件的构造函数,则根据参数类型计算权重,类型越匹配,优先级越高。
	 * 如果优先级一样,并且构造函数解析模式是宽松模式,则会使用排在前面的构造函数。
	 * 如果是严格模式,存在优先级一样的构造函数,会抛出异常。这主要发生在根据索引或名称匹配的时候。
	 * 构造函数的解析模式,默认是宽松模式。
	 */
	Constructor<?> constructorToUse = null;
	ArgumentsHolder argsHolderToUse = null; // 保存构造函数参数值的对象
	Object[] argsToUse = null; // 构造函数的参数值

	if (explicitArgs != null) { // explicitArgs是从getBean方法传入的参数值
		argsToUse = explicitArgs;
	}
	else {
		Object[] argsToResolve = null;
		synchronized (mbd.constructorArgumentLock) {
			/*
			 * 构造函数是否已经被解析过
			 * 第一次实例化Bean时,解析Bean定义,找到实例化Bean的构造函数,
			 * 然后会将构造函数回写到Bean定义中的resolvedConstructorOrFactoryMethod属性,
			 * 如果是有参构造函数,将constructorArgumentsResolved属性设置为true。
			 * 当下次再需要实例化这个Bean时,就无须再次解析,直接从Bean定义中获取即可,这是对非单例作用域的Bean实例化过程的优化
			 */
			constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
			if (constructorToUse != null && mbd.constructorArgumentsResolved) {
				// Found a cached constructor...
				argsToUse = mbd.resolvedConstructorArguments;
				if (argsToUse == null) {
					argsToResolve = mbd.preparedConstructorArguments;
				}
			}
		}
		if (argsToResolve != null) {
			// 解析缓存在 bean 定义中的参数
			argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
		}
	}

	if (constructorToUse == null || argsToUse == null) {
		// Take specified constructors, if any.
		// chosenCtors是AutowiredAnnotationBeanPostProcessor解析得到的构造函数,如果仅使用xml配置,这个值为null
		Constructor<?>[] candidates = chosenCtors;
		if (candidates == null) {
			Class<?> beanClass = mbd.getBeanClass(); // Bean的类型
			try {
				// 获取Bean class中的所有构造函数
				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);
			}
		}

		// 只有一个构造函数,并且Bean定义中没有显示的配置构造函数参数,才执行这块代码
		if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
			Constructor<?> uniqueCandidate = candidates[0];
			if (uniqueCandidate.getParameterCount() == 0) { // Bean的class中只要无参构造函数时,才走这一块代码
				synchronized (mbd.constructorArgumentLock) {
					mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
					mbd.constructorArgumentsResolved = true;
					mbd.resolvedConstructorArguments = EMPTY_ARGS;
				}
				// 通过反射的方式执行构造函数,实例Bean
				bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
				return bw;
			}
		}

		// Need to resolve the constructor.
		/*
		 * 是否是构造函数自动注入,注意:说的是自动注入
		 * 通过AutowiredAnnotationBeanPostProcessor解析得到的构造函数,当做构造函数自动注入
		 *  这种方式定义的Bean,使用构造函数自动注入
		 * 在构造函数上使用了@Autowire注解,也是构造函数自动注入
		 * 通过Java配置类定义的Bean,无论方法参数是否有值,都会被认为是构造函数自动注入
		 * 静态工厂和实例工厂定义的Bean,不是构造函数自动注入
		 * 在Bean定义时,显示指定了构造函数参数(constructor-arg),不是构造函数自动注入
		 */
		boolean autowiring = (chosenCtors != null ||
				mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);

		/*
		 * 用于保存构造函数参数值的对象
		 * 如果是通过索引配置的参数,则使用一个Map保存参数,key是下标值,value是参数值
		 * 如果是类型、参数名称等其他配置方式,则使用一各List保存参数
		 */
		ConstructorArgumentValues resolvedValues = null;

		int minNrOfArgs; // 构造函数最少的参数数量
		if (explicitArgs != null) {
			minNrOfArgs = explicitArgs.length;
		}
		else {
			// 获取Bean定义中显示配置的构造函数参数信息
			// Bean定义中的参数可能只是一个引用,而不是我们需要的对象,所以下面的方法根据引用找到对应的实例对象
			ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
			// 用于存储已经转换过的参数值,在 resolveConstructorArguments 方法中会给这个对象回写值
			resolvedValues = new ConstructorArgumentValues();
			/*
			 * 解析构造函数的参数值,如果在构造函数的配置中指定的其它Bean还没有创建,此处会将需要的Bean创建出来。
			 * 通过索引配置的参数是单独一种解析方法,解析的结果保存在一个Map中,key是索引,value是值对象。
			 * 通过默认(只配置了值)、类型、名称配置的参数是同一种解析方法,解析结果保存在一个List中。
			 * 通过构造器注入,没有显示配置参数时,这一段代码什么都不做。
			 * 返回值是配置的参数数量,构造函数的参数数量必须大于等于这个值。
			 */
			minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
		}

		// 构造函数排序,先根据限定符(public、private等)排序,public修饰的排在前面,限定符相同,再根据参数数量排序,参数多的排在前面
		AutowireUtils.sortConstructors(candidates);
		// 构造函数的权重,表示参数值的类型与构造函数参数类型之间的匹配度,类型越接近,值越小,优先级越高
		int minTypeDiffWeight = Integer.MAX_VALUE;
		// 模糊构造函数集合,即能够找到多个符合条件的构造函数,如果是严格模式,会抛出异常
		Set<Constructor<?>> ambiguousConstructors = null;
		// 用于缓存参数解析异常的对象,如果所有的构造函数都解析失败了,才会在最后抛出异常,只要有一个构造函数能与参数匹配成功,则无需抛出异常
		LinkedList<UnsatisfiedDependencyException> causes = null;

		for (Constructor<?> candidate : candidates) {

			int parameterCount = candidate.getParameterCount(); // 构造函数的参数数量

			/*
			 * 已找到了一个较为匹配的构造函数,并且当前遍历的构造函数的参数比已找到的那个少,就不要再查找了。
			 * 因为构造函数已经按参数数量做过排序了,可以理解为构造函数的参数比定义的参数少。
			 */
			if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
				// Already found greedy constructor that can be satisfied ->
				// do not look any further, there are only less greedy constructors left.
				break;
			}
			if (parameterCount < minNrOfArgs) { // 构造函数的参数值数量,不能小于 constructor-arg 配置的参数数量
				continue;
			}

			ArgumentsHolder argsHolder; // 用于保存构造函数需要的参数值
			Class<?>[] paramTypes = candidate.getParameterTypes(); // 构造函数的参数类型
			// 从上面的代码可以看出,只要调用getBean方法时,没有传入用于创建Bean的参数,resolvedValues就不会为null,最多为empty
			if (resolvedValues != null) {
				try {
					// 构造函数参数的名称
					String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
					if (paramNames == null) {
						// 使用参数名称解析器 DefaultParameterNameDiscoverer 解析参数名称
						ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
						if (pnd != null) {
							paramNames = pnd.getParameterNames(candidate); // 遍历各种解析策略,解析参数名称
						}
					}

					/*
					 * 解析构造函数的参数
					 * 配置的参数与构造函数需要的参数是否匹配,如果不匹配,会抛出异常,然后再解析下一个构造函数,如果所有的构造函数都不匹配,才会向外层抛出异常
					 * 构造函数自动注入的参数就是在这里进行获取的
					 */
					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 LinkedList<>();
					}
					causes.add(ex);
					continue;
				}
			}
			else {
				// Explicit arguments given -> arguments length must match exactly.
				if (parameterCount != explicitArgs.length) {
					continue;
				}
				argsHolder = new ArgumentsHolder(explicitArgs);
			}

			/*
			 * 根据宽松模式还是严格模式,使用不同的方法计算参数值与构造参数类型之间的差异。
			 * 值类型与参数类型之间的差异越小(计算结果越小),优先级越高。
			 * 例如对于 Integer 类型的参数,构造函数 (Integer) 将优于构造函数 (Number),而后者又将优于构造函数 (Object)
			 */
			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);
			}
		}

		// 如果没有找到符合条件的构造函数,则抛出异常
		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 " +
					"(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 in bean '" + beanName + "' " +
					"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
					ambiguousConstructors);
		}

		// 将解析结果回写到Bean定义对象的相关属性,再次创建Bean时,就不需要这么麻烦的解析了
		if (explicitArgs == null && argsHolderToUse != null) {
			argsHolderToUse.storeCache(mbd, constructorToUse);
		}
	}

	Assert.state(argsToUse != null, "Unresolved constructor arguments");
	// 通过反射的方式执行构造函数实例化Bean。构造函数依赖注入的Bean在上面被解析、找到,在这里用来实例化
	bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
	return bw;
}

使用构造函数实例化Bean,主要有以下几个步骤:

  1. 找出可用于实例化Bean的构造函数,可能找到多个,此时需要根据参数进行匹配查找。
  2. 解析配置的参数值,根据索引、类型、名称等解析出配置的参数,如果是一个Bean,又还没有创建,则此处会创建这个Bean。
  3. 将配置参数与构造函数的实际参数类型做匹配,找出最终用于实例化的构造函数,如果找不到,则实例化失败。
  4. 将构造函数、参数等数据回写到Bean定义对象的相关属性上,再次创建相同的Bean时,就无需解析,直接从Bean定义中取即可。
  5. 使用反射的方式实例化Bean。
参数解析和参数类型转换

构造函数的参数解析、参数类型转换与工厂方法参数的解析、转换调用的相同的方法。
具体的代码可以查看上面的内容。

执行构造函数,实例化Bean
// ConstructorResolver
private Object instantiate(
		String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) {

	try {
		InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
		if (System.getSecurityManager() != null) {
			return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
					strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),
					this.beanFactory.getAccessControlContext());
		}
		else {
		    // 通过反射的方式实例化Bean,Constructor.newInstance(args)
			return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
		}
	}
	catch (Throwable ex) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
				"Bean instantiation via constructor failed", ex);
	}
}
// SimpleInstantiationStrategy
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
		final Constructor<?> ctor, Object... args) {

	if (!bd.hasMethodOverrides()) {
		if (System.getSecurityManager() != null) {
			// use own privileged to change accessibility (when security is on)
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				ReflectionUtils.makeAccessible(ctor);
				return null;
			});
		}
		// 使用反射创建Bean实例
		return BeanUtils.instantiateClass(ctor, args);
	}
	else {
		return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
	}
}
// BeanUtils
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
	Assert.notNull(ctor, "Constructor must not be null");
	try {
		ReflectionUtils.makeAccessible(ctor); // 将构造函数设置为可访问
		if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
			return KotlinDelegate.instantiateClass(ctor, args);
		}
		else {
		    // 获取构造函数的参数类型
			Class<?>[] parameterTypes = ctor.getParameterTypes();
			Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
			Object[] argsWithDefaultValues = new Object[args.length];
			for (int i = 0 ; i < args.length; i++) { // 构造函数的参数处理
				if (args[i] == null) { // 如果参数值为空,获取默认值
					Class<?> parameterType = parameterTypes[i];
					argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
				}
				else {
					argsWithDefaultValues[i] = args[i];
				}
			}
			return ctor.newInstance(argsWithDefaultValues); // 使用构造函数创建Bean实例
		}
	}
	// 省略掉所有异常处理的代码
}

别看代码量比较多,实际也就是一行代码的事情,就是通过反射调用构造函数 Constructor.newInstance(args)

当我们需要使用反射创建一个对象的是,也可以使用Spring的工具类方法BeanUtils.instantiateClass(Constructor ctor, Object... args)

默认无参构造函数实例化Bean
// AbstractAutowireCapableBeanFactory
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
	try {
		Object beanInstance;
		final BeanFactory parent = this; // IoC容器
		if (System.getSecurityManager() != null) {
			beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
					getInstantiationStrategy().instantiate(mbd, beanName, parent),
					getAccessControlContext());
		}
		else {
			// 通过反射,执行构造函数实例化Bean
			beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
		}
		// 返回一个包装类
		BeanWrapper bw = new BeanWrapperImpl(beanInstance);
		initBeanWrapper(bw);
		return bw;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
	}
}
// SimpleInstantiationStrategy
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
	// Don't override the class with CGLIB if no overrides.
	// 如果不存在方法覆写(lookup-method 和 replaced-method),那就使用 java 反射进行实例化,否则使用 CGLIB
	if (!bd.hasMethodOverrides()) {
		Constructor<?> constructorToUse;
		synchronized (bd.constructorArgumentLock) {
		    // 构造函数或工厂方法是否有被解析过,第一次解析时会将构造函数或工厂方法回写到Bean定义中
			constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
			if (constructorToUse == null) {
				final Class<?> clazz = bd.getBeanClass(); // Bean的类型
				if (clazz.isInterface()) { // 如果类型是接口,直接抛出异常
					throw new BeanInstantiationException(clazz, "Specified class is an interface");
				}
				try {
					if (System.getSecurityManager() != null) {
						constructorToUse = AccessController.doPrivileged(
								(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
					}
					else {
						// 获取class的默认构造函数
						constructorToUse = clazz.getDeclaredConstructor();
					}
					// 将构造函数回写到Bean定义中,下次再创建实例时,无须再次解析
					bd.resolvedConstructorOrFactoryMethod = constructorToUse;
				}
				catch (Throwable ex) {
					throw new BeanInstantiationException(clazz, "No default constructor found", ex);
				}
			}
		}
		// 使用反射的方式创建Bean实例
		return BeanUtils.instantiateClass(constructorToUse);
	}
	else {
		// Must generate CGLIB subclass.
		// 存在方法覆写,利用 CGLIB 来完成实例化,需要依赖于 CGLIB 生成子类
		return instantiateWithMethodInjection(bd, beanName, owner);
	}
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/800193.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-06
下一篇 2022-05-06

发表评论

登录后才能评论

评论列表(0条)

保存