Spring源码深度解析:九、bean的获取② - createBeanInstance

news2025/8/17 4:31:44

createBeanInstance()的流程图如下,让我们根据流程图一步一步的学习一下spring是如何创建bean的吧
在这里插入图片描述

一、前言

文章目录:Spring源码分析:文章目录

这篇文章应该是接着 Spring源码深度解析:八、bean的获取② - getSingleton 的继续分析过程。
本文主要是分析的方法是AbstractAutowireCapableBeanFactory#createBeanInstance(),功能是Spring 具体创建bean的过程。调用如下:
在这里插入图片描述

二、createBeanInstance 概述

createBeanInstance()根据方法名就知道,是创建bean的实例,也就注定了这个方法的不平凡。下面就来一步一步的剖析他。

具体源码如下:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		// 解析bean,获取class
		Class<?> beanClass = resolveBeanClass(mbd, beanName);
		// beanClass != null && 当前类不是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());
		}
		// 1. 是否有bean的Supplier接口,如果有,通过回调来创建bean
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		// 2. 如果工厂方法不为空,则使用工厂方法初始化策略
		// 通过@Bean注解方法注入的bean或者xml配置注入的BeanDefinition会存在这个值。而注入这个bean的方法就是工厂方法。后面会详细解读
		if (mbd.getFactoryMethodName() != null) {
			// 执行工厂方法,创建bean
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		// 3. 尝试使用构造函数构建bean,后面详解
		// 经过上面两步,Spring确定没有其他方式来创建bean,所以打算使用构造函数来进行创建bean。 但是 bean的构造函数可能有多个,需要确定使用哪一个。
		// 这里实际上是一个缓存,resolved表示构造函数是否已经解析完成;autowireNecessary表示是否需要自动装配
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					// 一个类可能有多个不同的构造函数,每个构造函数参数列表不同,所以调用前需要根据参数锁定对应的构造函数或工程方法
					// 如果这个bean的构造函数或者工厂方法已经解析过了,会保存到 mbd.resolvedConstructorOrFactoryMethod 中。这里来判断是否已经解析过了。
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		// 如果已经解析过则使用功能解析好的构造函数方法,不需要再次解析。这里的是通过 mbd.resolvedConstructorOrFactoryMethod 属性来缓存解析过的构造函数。
		if (resolved) {
			if (autowireNecessary) {
				// 4. 构造函数自动注入
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				// 5. 使用默认构造函数构造
				return instantiateBean(beanName, mbd);
			}
		}

		// Candidate constructors for autowiring?
		// 6. 根据参数解析构造函数,并将解析出来的构造函数缓存到mdb的  resolvedConstructorOrFactoryMethod属性中
		// 到这一步,说明 bean 是第一次加载,所以没有对构造函数进行相关缓存(resolved 为 false)
		// 调用 determineConstructorsFromBeanPostProcessors方法来获取指定的构造函数列表。后面详解
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			return autowireConstructor(beanName, mbd, ctors, args);
		}

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

我们可以看到:

  1. 如果RootBeanDefinition中存在Supplier供应商接口,则使用Supplier的回调来创建bean。 Supplier是用来替代声明式指定的工厂。
  2. 如果RootBeanDefinition中存在factoryMethodName属性,或者在配置文件中配置了factory-method,Spring会尝试使用instantiateUsingFactoryMethod()方法,根据RootBeanDefinition中的配置生成bean实例。需要注意的是,如果一个类中的方法被@Bean注解修饰,那么Spring则会将其封装成一个 ConfigurationClassBeanDefinition。此时factoryMethodName也被赋值。所以也会调用instantiateUsingFactoryMethod方法通过反射完成方法的调用,并将结果注入Spring容器中。
  3. 当以上两种都没有配置时,Spring则打算通过bean的构造函数来创建bean。首先会判断是否有缓存,即构造函数是否已经被解析过了, 因为一个bean可能会存在多个构造函数,这时候Spring会根据参数列表的来判断使用哪个构造函数进行实例化。但是判断过程比较消耗性能,所以Spring将判断好的构造函数缓存到RootBeanDefinition中的resolvedConstructorOrFactoryMethod属性中。
  4. 如果存在缓存,则不需要再次解析筛选构造函数,直接调用autowireConstructor或者instantiateBean方法创建bean。有参构造调用autowireConstructor方法,无参构造调用instantiateBean方法。
  5. 如果不存在缓存则需要进行解析,这里通过determineConstructorsFromBeanPostProcessors方法调用了 SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors() 的后处理器方法来进行解析,Spring 默认的实现在AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors()方法中。通过determineCandidateConstructors方法获取到了候选的构造函数(因为满足条件的构造函数可能不止一个,需要进行进一步的选择)。
  6. 获取解析后的候选的构造函数列表 ctors 后(最终的构造函数就从这个列表中选取),开始调用autowireConstructor或者 instantiateBean方法创建bean。在autowireConstructor中,进行了候选构造函数的选举,选择最合适的构造函数来构建bean,如果缓存已解析的构造函数,则不用选举,直接使用解析好的构造来进行bean的创建。

三、createBeanInstance 详解

下面我们来解析代码。

1. 调用 Supplier 接口 - obtainFromSupplier

这部分的功能 : 若RootBeanDefinition中设置了Supplier则使用 Supplier提供的bean替代Spring要生成的bean

		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}
@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

AbstractAutowireCapableBeanFactory#obtainFromSupplier()

protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
		Object instance;
		// 使用临时变量保存currentlyCreatedBean当前值
		String outerBean = this.currentlyCreatedBean.get();
		// 将beanName设置到currentlyCreatedBean中,表示这是当前正在创建到bean
		// currentlyCreatedBean.get()在getObjectForBeanInstance中会被调用(通过对currentlyCreatedBean使用find Usages发现)
		this.currentlyCreatedBean.set(beanName);
		try {
			// 执行lambda表达式的 Supplier函数来生成一个实例对象
			instance = instanceSupplier.get();
		}
		finally {
			// 还原原来的临时变量
			if (outerBean != null) {
				this.currentlyCreatedBean.set(outerBean);
			}
			else {
				this.currentlyCreatedBean.remove();
			}
		}
		// 如果得到的实例为null,则会去创建一个空实例
		if (instance == null) {
			instance = new NullBean();
		}
		// 构造一个bean包装器,BeanWrapperImpl内初始化了几个参数,无其他逻辑
		BeanWrapper bw = new BeanWrapperImpl(instance);
		initBeanWrapper(bw);
		return bw;
	}
  • 首先,调用 Supplier 的 get() 方法,获得一个 Bean 实例对象。
  • 然后,根据该实例对象构造一个 BeanWrapper 对象 bw 。
  • 最后,初始化该对象。

关于其应用场景 : 指定一个用于创建bean实例的回调,以替代声明式指定的工厂方法。主要是考虑反射调用目标方法不如直接调用目标方法效率高。

2. 使用 factory-method 属性 - instantiateUsingFactoryMethod

如果RootBeanDefinition中存在factoryMethodName属性,或者在配置文件中配置了factory-method,Spring会尝试使用instantiateUsingFactoryMethod方法,根据RootBeanDefinition中的配置生成bean实例。简单来说,就是如果BeanDefinition指定了工厂方法,则使用其指定的工厂方法来初始化bean。

简单来说,这里可以分为两种情况

  1. 在 xml配置中,可以使用factory-beanfactory-method两个标签可以指定一个类中的方法,Spring会将这个指定的方法的返回值作为bean返回(如果方法是静态方法,则可以不创建factorybean就直接调用,否则需要先将factorybean注入到Spring中)。

  2. @Bean注解的解析。在ConfigurationClassPostProcessor后处理器中,会对被@Bean注解修饰的方法进行解析,生成一个ConfigurationClassBeanDefinitionBeanDefinition。此时BeanDefinitionfactoryMethodName正是@Bean修饰的方法本身。所以这里会调用 instantiateUsingFactoryMethod方法。通过回调的方式调用@Bean修饰的方法。并将返回结果注入到Spring容器中。

		// 2. 如果工厂方法不为空,则使用工厂方法初始化策略
		// 通过 @Bean 注解方法注入的bean或者xml配置注入的BeanDefinition会存在这个值。而注入这个bean的方法就是工厂方法。后面会详细解读
		if (mbd.getFactoryMethodName() != null) {
			// 执行工厂方法,创建bean
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

ConstructorResolver#instantiateUsingFactoryMethod()

public BeanWrapper instantiateUsingFactoryMethod(
			String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
		//构造bean的包装类
		BeanWrapperImpl bw = new BeanWrapperImpl();
		//初始化包装类
		this.beanFactory.initBeanWrapper(bw);

		Object factoryBean;
		Class<?> factoryClass;
		boolean isStatic;
		//获得bean的工厂名字
		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");
			}
			//根据名字获得bean的工厂
			factoryBean = this.beanFactory.getBean(factoryBeanName);
			//假如bean是单例,且工厂已经存在
			if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
				throw new ImplicitlyAppearedSingletonException();
			}
			// 获得工厂字节码
			factoryClass = factoryBean.getClass();
			isStatic = false;
		}
		else {
			// 工厂名为空,则其可能是一个静态工厂
			// 静态工厂创建bean,必须要提供工厂的全类名
			// 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;
		}

		// 获得 factoryMethodToUse、argsHolderToUse、argsToUse 属性
		Method factoryMethodToUse = null;
		ArgumentsHolder argsHolderToUse = null;
		Object[] argsToUse = null;

		// 如果指定了构造方法的参数,则构造bean 的时候使用此构造方法
		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		else {
			// 没有指定,则尝试从配置文件中解析
			Object[] argsToResolve = null;
			synchronized (mbd.constructorArgumentLock) {
				// 尝试用构造工厂中获取
				factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
				if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
					// Found a cached factory method...
					// 尝试从缓存中获取
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						// 获取缓存中的构造函数参数的包可见字段
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			// 缓存中存在,则解析存储在 BeanDefinition 中的参数
			// 如给定方法的构造函数 A(int ,int ),则通过此方法后就会把配置文件中的("1","1")转换为 (1,1)
			// 缓存中的值可能是原始值也有可能是最终值
			if (argsToResolve != null) {
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);
			}
		}

		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.
			// 获取工厂方法的全名称
			factoryClass = ClassUtils.getUserClass(factoryClass);
			// 获取所有的待定方法
			Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
			List<Method> candidateList = new ArrayList<>();
			// 检索所有方法,这里是对方法进行过滤
			for (Method candidate : rawCandidates) {
				// 如果有方法为静态方法,且为工厂方法则添加到candidateList中
				if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
					candidateList.add(candidate);
				}
			}
			// 排序构造函数
			Method[] candidates = candidateList.toArray(new Method[0]);
			// public 构造函数优先参数数量降序,非 public 构造函数参数数量降序
			AutowireUtils.sortFactoryMethods(candidates);
			// 用来承载解析后构造函数的值
			ConstructorArgumentValues resolvedValues = null;
			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.
				// 如果getBean没有传递参数,则需要解析保存在 BeanDefinition 构造函数中指定的参数
				if (mbd.hasConstructorArgumentValues()) {
					// 构造函数的参数
					ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
					resolvedValues = new ConstructorArgumentValues();
					// 将构造函数的参数解析进resolvedValues中
					minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
				}
				else {
					minNrOfArgs = 0;
				}
			}

			LinkedList<UnsatisfiedDependencyException> causes = null;
			// 遍历 candidates 数组
			for (Method candidate : candidates) {
				// 方法体的参数
				Class<?>[] paramTypes = candidate.getParameterTypes();

				if (paramTypes.length >= minNrOfArgs) {
					// 保存参数的对象
					ArgumentsHolder argsHolder;

					// 传递了参数
					if (explicitArgs != null) {
						// Explicit arguments given -> arguments length must match exactly.
						// 显示给定参数,参数长度必须完全匹配
						if (paramTypes.length != explicitArgs.length) {
							continue;
						}
						// 根据参数创建参数持有者 ArgumentsHolder 对象
						argsHolder = new ArgumentsHolder(explicitArgs);
					}
					else {
						// 未提供参数
						// Resolved constructor arguments: type conversion and/or autowiring necessary.
						try {
							String[] paramNames = null;
							// 获取 ParameterNameDiscoverer 对象
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
							if (pnd != null) {
								// 获取指定构造函数的参数名称
								paramNames = pnd.getParameterNames(candidate);
							}
							// 在已经解析的构造函数参数值的情况下,创建一个参数持有者 ArgumentsHolder 对象
							argsHolder = createArgumentArray(
									beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
						}
						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;
						}
					}
					// isLenientConstructorResolution 判断解析构造函数的时候是否以宽松模式还是严格模式
					// 严格模式:解析构造函数时,必须所有的都需要匹配,否则抛出异常
					// 宽松模式:使用具有"最接近的模式"进行匹配
					// typeDiffWeight:类型差异权重
					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;
						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);
					}
				}
			}
			// 没有可执行的工厂方法,抛出异常
			if (factoryMethodToUse == 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") + ".");
			}
			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) {
				argsHolderToUse.storeCache(mbd, factoryMethodToUse);
			}
		}

		try {
			Object beanInstance;

			if (System.getSecurityManager() != null) {
				final Object fb = factoryBean;
				final Method factoryMethod = factoryMethodToUse;
				final Object[] args = argsToUse;
				beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
						beanFactory.getInstantiationStrategy().instantiate(mbd, beanName, beanFactory, fb, factoryMethod, args),
						beanFactory.getAccessControlContext());
			}
			else {
				beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
						mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);
			}
			// 创建 Bean 对象,并设置到 bw 中
			bw.setBeanInstance(beanInstance);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean instantiation via factory method failed", ex);
		}
	}

2.1 storeCache将构造函数、构造参数保存到缓存中

ConstructorResolver#storeCache()

public void storeCache(RootBeanDefinition mbd, Executable constructorOrFactoryMethod) {
			// 构造函数的缓存锁
			synchronized (mbd.constructorArgumentLock) {
				// 缓存已经解析的构造函数或者工厂方法
				mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
				// 标记字段,标记构造函数、参数已经解析了。默认为 false
				mbd.constructorArgumentsResolved = true;
				if (this.resolveNecessary) {
					// 缓存已经解析的构造函数参数,包可见字段
					mbd.preparedConstructorArguments = this.preparedArguments;
				}
				else {
					mbd.resolvedConstructorArguments = this.arguments;
				}
			}
		}

2.2instantiate创建Bean

InstantiationStrategy#instantiate()

Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
			@Nullable Object factoryBean, Method factoryMethod, @Nullable Object... args)
			throws BeansException;

SimpleInstantiationStrategy#instantiate()

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
			@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
 
		try {
			// 设置 Method 可访问
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
					ReflectionUtils.makeAccessible(factoryMethod);
					return null;
				});
			}
			else {
				ReflectionUtils.makeAccessible(factoryMethod);
			}
			// 获得原 Method 对象
			Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
			try {
				// 设置新的 Method 对象,到 currentlyInvokedFactoryMethod 中
				currentlyInvokedFactoryMethod.set(factoryMethod);
				// 创建bean
				Object result = factoryMethod.invoke(factoryBean, args);
				// bean不存在则创建nullbean
				if (result == null) {
					result = new NullBean();
				}
				return result;
			}
			finally {
				if (priorInvokedFactoryMethod != null) {
					currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
				}
				else {
					currentlyInvokedFactoryMethod.remove();
				}
			}
		}
		catch (IllegalArgumentException ex) {
			throw new BeanInstantiationException(factoryMethod,
					"Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
					"args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
		}
		catch (IllegalAccessException ex) {
			throw new BeanInstantiationException(factoryMethod,
					"Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
		}
		catch (InvocationTargetException ex) {
			String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
			if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
					((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
				msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
						"declaring the factory method as static for independence from its containing instance. " + msg;
			}
			throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
		}
	}

3. 构造函数的缓存判断

到达这一步,Spring则打算通过bean的构造函数来创建bean。但是一个bean可能会存在多个构造函数,这时候Spring会根据参数列表的来判断使用哪个构造函数进行实例化。但是判断过程比较消耗性能,所以Spring将判断好的构造函数缓存到RootBeanDefinition中,如果不存在缓存则进行构造函数的筛选并缓存解析结果。RootBeanDefinition 中具体的缓存属性有如下几个:

RootBeanDefinition 中主要使用如下几个属性缓存 :

  • resolvedConstructorOrFactoryMethod: 用于缓存已解析的构造函数或工厂方法
  • constructorArgumentsResolved:这个字段有两层含义: 一,标记构造函数是否已经完成解析。二,标志这个bean的加载是否需要通过构造注入(autowireConstructor) 的方式加载。因为只有在autowireConstructor方法中才会将其置为 true。
  • resolvedConstructorArguments: 缓存解析好的构造函数的入参
		// 经过上面两步,Spring确定没有其他方式来创建bean,所以打算使用构造函数来进行创建bean。 但是 bean 的构造函数可能有多个,需要确定使用哪一个。
		// 这里实际上是一个缓存,resolved表示构造函数是否已经解析完成;autowireNecessary表示是否需要自动装配
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				// 一个类可能有多个不同的构造函数,每个构造函数参数列表不同,所以调用前需要根据参数锁定对应的构造函数或工程方法
				// 如果这个bean的构造函数或者工厂方法已经解析过了,会保存到 mbd.resolvedConstructorOrFactoryMethod 中。这里来判断是否已经解析过了。
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		// 如果已经解析过则使用功能解析好的构造函数方法,不需要再次解析。这里的是通过 mbd.resolvedConstructorOrFactoryMethod 属性来缓存解析过的构造函数。
		if (resolved) {
			if (autowireNecessary) {
				// 4. 构造函数自动注入
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				// 5. 使用默认构造函数构造
				return instantiateBean(beanName, mbd);
			}
		}

4. 带有参数的构造函数实例化 - autowireConstructor

上面的代码我们可以看到,Bean的的创建,分为有参构造函数和无参构造函数两种方式进行创建,对于有参构造函数,使用的就是该方法进行处理。这个代码量非常巨大,实现的功能实现上比较复杂,功能上却可以一句话讲清,简单来说,就是根据传入的参数列表,来匹配到合适的构造函数进行bean 的创建。

	autowireConstructor(beanName, mbd, null, null);

autowireConstructor的代码比较复杂,详细代码如下:
AbstractAutowireCapableBeanFactory#autowireConstructor()

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

		return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
	}

ConstructorResolver#autowireConstructor()

	//   chosenCtors :  候选构造函数列表, 没有则为null
	//   explicitArgs : 通过getBean方法以编程方式传递的参数值,
	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;

		// 1. 解析构造函数参数
		// explicitArgs  参数是通过 getBean 方法传入
		// 如果getBean在调用时传入了参数,那么直接使用即可。getBean调用的传参,不用从缓存中获取构造函数,需要进行筛选匹配(个人理解,getBean方法的入参可能并不相同,缓存的构造函数可能并不适用)
		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		else {
			// 否则 尝试从 BeanDefinition 中加载缓存的bean构造时需要的参数
			Object[] argsToResolve = null;
			// 加锁
			synchronized (mbd.constructorArgumentLock) {
				// 从缓存中获取要使用的构造函数。没有缓存则为null
				constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
				// 如果构造函数不为空 && 构造函数参数已经解析
				if (constructorToUse != null && mbd.constructorArgumentsResolved) {
					// Found a cached constructor...
					// 从缓存中获取。这里如果不能获取到完全解析好的参数,则获取尚未解析的参数,进行解析后再赋值给 argsToUse
					// resolvedConstructorArguments 是完全解析好的构造函数参数
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						// 配置构造函数参数
						// preparedConstructorArguments是尚未完全解析的构造函数参数
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			//  如果缓存中存在 尚未完全解析的参数列表,则进行进一步的解析
			if (argsToResolve != null) {
				// 解析参数类型,如给定的参数列表为(int,int),这时就会将配置中的("1", "1") 转化为 (1,1)
				// 缓存中的值可能是最终值,也可能是原始值,因为不一定需要类型转换
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
			}
		}

		// 如果构造函数 和 构造函数入参都不为空,则可以直接生成bean。否则的话,需要通过一定的规则进行筛选
		if (constructorToUse == null) {
			// Need to resolve the constructor.
			boolean autowiring = (chosenCtors != null ||
					mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
			ConstructorArgumentValues resolvedValues = null;

			int minNrOfArgs;
			if (explicitArgs != null) {
				minNrOfArgs = explicitArgs.length;
			}
			else {
				ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
				resolvedValues = new ConstructorArgumentValues();
				minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
			}

			// Take specified constructors, if any.
			// chosenCtors 是候选的构造函数,如果存在候选的构造函数,则跳过这里,否则通过反射获取bean的构造函数集合
			// 2. 获取候选的构造参数列表
			Constructor<?>[] candidates = chosenCtors;
			if (candidates == null) {
				Class<?> beanClass = mbd.getBeanClass();
				try {
					// 反射获取bean的构造函数集合
					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);
				}
			}
			// 3. 寻找最匹配的构造函数
			// 对构造函数列表进行排序: public 构造函数优先参数数量降序,非public构造函数参数数量降序
			AutowireUtils.sortConstructors(candidates);
			int minTypeDiffWeight = Integer.MAX_VALUE;
			Set<Constructor<?>> ambiguousConstructors = null;
			LinkedList<UnsatisfiedDependencyException> causes = null;
			// 遍历构造函数,寻找合适的构造函数
			for (Constructor<?> candidate : candidates) {
				Class<?>[] paramTypes = candidate.getParameterTypes();
				// 如果构造函数存在参数,resolvedValues 是上面解析后的构造函数,有参则根据 值 构造对应参数类型的参数
				if (constructorToUse != null && argsToUse.length > paramTypes.length) {
					// Already found greedy constructor that can be satisfied ->
					// do not look any further, there are only less greedy constructors left.
					break;
				}
				if (paramTypes.length < minNrOfArgs) {
					continue;
				}

				ArgumentsHolder argsHolder;
				if (resolvedValues != null) {
					try {
						// 获取参数名称
						String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
						// 为null则说明没有使用注解
						if (paramNames == null) {
							// 获取参数名称探索器
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
							if (pnd != null) {
								// 获取指定的构造函数的参数名称
								paramNames = pnd.getParameterNames(candidate);
							}
						}
						// 根据类型和数据类型创建 参数持有者
						// 这里会调用  DefaultListableBeanFactory#resolveDependency 方法来解析依赖关系
						argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
								getUserDeclaredConstructor(candidate), autowiring);
					}
					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 (paramTypes.length != explicitArgs.length) {
						continue;
					}
					// 构造函数没有参数的情况
					argsHolder = new ArgumentsHolder(explicitArgs);
				}
				// 探测是否有不确定性的构造函数存在,例如不同构造函数的参数为父子关系
				int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
						argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
				// Choose this constructor if it represents the closest match.
				// 如果他是当前最接近匹配则选择作为构造函数,因为可能有多个构造函数都同时满足,比如构造函数参数类型全是 Object,选择最合适的(typeDiffWeight 最小的)作为最终构造函数
				if (typeDiffWeight < minTypeDiffWeight) {
					// 找到最匹配的构造函数赋值保存
					constructorToUse = candidate;
					argsHolderToUse = argsHolder;
					argsToUse = argsHolder.arguments;
					minTypeDiffWeight = typeDiffWeight;
					ambiguousConstructors = null;
				}
				else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
					// 如果 已经找到候选构造函数,且当前这个构造函数也有相同的类似度则保存到 ambiguousConstructors 中。后面用于抛出异常
					if (ambiguousConstructors == null) {
						ambiguousConstructors = new LinkedHashSet<>();
						ambiguousConstructors.add(constructorToUse);
					}
					ambiguousConstructors.add(candidate);
				}
			}
			// 如果 constructorToUse  构造函数为  null,则查找构造函数失败,抛出异常
			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)");
			}
			// 如果ambiguousConstructors 不为空说明有多个构造函数可适配,并且 如果不允许多个存在,则抛出异常
			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);
			}
			// 将解析的构造函数加入缓存
			if (explicitArgs == null) {
				argsHolderToUse.storeCache(mbd, constructorToUse);
			}
		}

		try {
			final InstantiationStrategy strategy = beanFactory.getInstantiationStrategy();
			Object beanInstance;

			if (System.getSecurityManager() != null) {
				final Constructor<?> ctorToUse = constructorToUse;
				final Object[] argumentsToUse = argsToUse;
				beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
						strategy.instantiate(mbd, beanName, beanFactory, ctorToUse, argumentsToUse),
						beanFactory.getAccessControlContext());
			}
			else {
				beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
			}
			// 将构建的实例加入BeanWrapper 中
			bw.setBeanInstance(beanInstance);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean instantiation via constructor failed", ex);
		}
	}

简单理一下上面的逻辑:

  1. 首先判断explicitArgs是否为空,如果不为空,则就直接使用explicitArgs作为构造函数的参数。
    explicitArgs所代表的意思是 调用getBean方法是的传参,代码中可以看到,如果 explicitArgs不为空,那么并未从缓存中获取构造函数(个人猜测 getBean 方法调用参数并不一致,可能缓存并不适用) 如下:
    在这里插入图片描述
  2. 如果explicitArgs为空,则尝试从之缓存中获取,也即是从RootBeanDefinitionresolvedConstructorArguments属性或 preparedConstructorArguments属性中获取。resolvedConstructorArguments代表完全解析好的参数,preparedConstructorArguments代表尚未完全解析的参数,如果获取到 preparedConstructorArguments ,则需要在进一步的解析。
  3. 如果缓存中也没有获取到,则只能自己开始分析来获取候选构造函数列表,关于候选构造函数的信息,在调用该方法时就已经传递了过来,即Constructor<?>[] chosenCtors,如果 Constructor<?>[] chosenCtorsnull,则通过反射获取候选构造函数列表 candidates
  4. 获取到候选构造函数列表candidates后,则会优先判断获取到的candidates是否只有一个构造函数,如果只要一个,则不需要解析,直接保存相关信息即解析完毕。
  5. 否则则进行候选构造函数列表candidates的选举,寻找最合适的构造函数,对 candidates按照public构造函数优先参数数量降序,非public构造函数参数数量降序 规则排序,目的是为了后面检索的时候可以更快速判断是否有合适的构造函数。
    排序结束后 ,开始遍历构造函数,按照 构造函数的参数类型和数量与构造函数一一匹配,寻找差异性最小的构造函数作为最终的构造函数并通过cglib或者反射来创建bean

按照功能划分,整个 autowireConstructor 方法可以划分为四步:

  1. 解析构造函数参数
  2. 获取候选的构造函数列表
  3. 解析构造函数参数个数
  4. 寻找最匹配的构造函数

下面分段解析:

4.1 解析构造函数参数

	// explicitArgs  参数是通过 getBean 方法传入
	// 如果 getBean在调用时传入了参数,那么直接使用即可。
	if (explicitArgs != null) {
		argsToUse = explicitArgs;
	}
	else {
		// 否则 尝试从配置文件中去加载bean构造时需要的参数
		Object[] argsToResolve = null;
		// 加锁
		synchronized (mbd.constructorArgumentLock) {
			// 从缓存中获取要使用的构造函数
			constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
			if (constructorToUse != null && mbd.constructorArgumentsResolved) {
				// Found a cached constructor...
				// 从缓存中获取。这里如果不能获取到完全解析好的参数,则获取尚未解析的参数,进行解析后再赋值给 argsToUse 
				// resolvedConstructorArguments 是完全解析好的构造函数参数
				argsToUse = mbd.resolvedConstructorArguments;
				if (argsToUse == null) {
					// 配置构造函数参数
					// preparedConstructorArguments 是尚未完全解析的构造函数参数
					argsToResolve = mbd.preparedConstructorArguments;
				}
			}
		}
		//  如果缓存中存在 尚未完全解析的参数列表,则进行进一步的解析
		if (argsToResolve != null) {
			// 解析参数类型,如给定的参数列表为(int,int),这时就会将配置中的("1", "1") 转化为 (1,1)
			// 缓存中的值可能是最终值,也可能是原始值
			argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
		}
	}

上面的逻辑还是很清楚的

  1. 如果有传入参数 explicitArgs,则直接使用 explicitArgs
  2. 如果没有传入,尝试从缓存中获取
  3. 如果参数完全解析了,则直接使用,如果没有则调用 resolvePreparedArguments 进行解析

这里解释一下resolvePreparedArguments方法的作用。

我们声明的构造函数的可能是这样的

    public ConstructorDemoA(Integer name) {
        this.name = name;
    }

但是我们在配置的时候xml配置文件却是这样的。

    <bean id="constructorDemoA" class="com.kingfish.springbootdemo.constructor.ConstructorDemoA">
        <constructor-arg index="0" value="666" ></constructor-arg>
    </bean>

这时候,Spring就需要有一个过程,从Spring 的 “666” 到 Integer 的 666 的转变,这个方法就是做类型转化的工作。但需要注意调用这个方法的前提条件是argsToResolve != null

4.2 获取候选的构造函数列表

// chosenCtors 是候选的构造函数,如果存在候选的构造函数,则跳过这里,否则通过反射获取bean的构造函数集合
			// 2. 获取候选的构造参数列表
			Constructor<?>[] candidates = chosenCtors;
			if (candidates == null) {
				Class<?> beanClass = mbd.getBeanClass();
				try {
					// 反射获取bean的构造函数集合
					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);
				}
			}

这个逻辑也是比较清楚的 chosenCtors 是传入的构造函数列表

  1. 外部是否传入了候选构造函数列表( chosenCtors == null)
  2. 如果没传入(chosenCtors 为null),通过反射获取构造函数列表

这里需要注意点是 传入的chosenCtors,在不同的调用场景下可能会传入null,或者 调用 SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors方法返回的值。Spring 默认的实现是在 AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors方法中。

4.3 寻找最匹配的构造函数

到这里,我们可以知道 minNrOfArgs 为最终构造函数入参数量;candidates 是供选择的构造函数列表。

代码比较长,上面已经贴出了完整版,这里就简化一下。

// 3. 寻找最匹配的构造函数
			// 对构造函数列表进行排序: public 构造函数优先参数数量降序,非public构造函数参数数量降序
			AutowireUtils.sortConstructors(candidates);
			int minTypeDiffWeight = Integer.MAX_VALUE;
			Set<Constructor<?>> ambiguousConstructors = null;
			LinkedList<UnsatisfiedDependencyException> causes = null;
			// 遍历构造函数,寻找合适的构造函数
			for (Constructor<?> candidate : candidates) {
				Class<?>[] paramTypes = candidate.getParameterTypes();
				// 如果构造函数存在参数,resolvedValues 是上面解析后的构造函数,有参则根据 值 构造对应参数类型的参数
				if (constructorToUse != null && argsToUse.length > paramTypes.length) {
					// Already found greedy constructor that can be satisfied ->
					// do not look any further, there are only less greedy constructors left.
					break;
				}
				if (paramTypes.length < minNrOfArgs) {
					continue;
				}

				ArgumentsHolder argsHolder;
				if (resolvedValues != null) {
					try {
						// 获取参数名称
						String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
						// 为null则说明没有使用注解
						if (paramNames == null) {
							// 获取参数名称探索器
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
							if (pnd != null) {
								// 获取指定的构造函数的参数名称
								paramNames = pnd.getParameterNames(candidate);
							}
						}
						// 根据类型和数据类型创建 参数持有者
						// 这里会调用  DefaultListableBeanFactory#resolveDependency 方法来解析依赖关系
						argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
								getUserDeclaredConstructor(candidate), autowiring);
					}
					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 (paramTypes.length != explicitArgs.length) {
						continue;
					}
					// 构造函数没有参数的情况
					argsHolder = new ArgumentsHolder(explicitArgs);
				}
				// 探测是否有不确定性的构造函数存在,例如不同构造函数的参数为父子关系
				int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
						argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
				// Choose this constructor if it represents the closest match.
				// 如果他是当前最接近匹配则选择作为构造函数,因为可能有多个构造函数都同时满足,比如构造函数参数类型全是 Object,选择最合适的(typeDiffWeight 最小的)作为最终构造函数
				if (typeDiffWeight < minTypeDiffWeight) {
					// 找到最匹配的构造函数赋值保存
					constructorToUse = candidate;
					argsHolderToUse = argsHolder;
					argsToUse = argsHolder.arguments;
					minTypeDiffWeight = typeDiffWeight;
					ambiguousConstructors = null;
				}
				else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
					// 如果 已经找到候选构造函数,且当前这个构造函数也有相同的类似度则保存到 ambiguousConstructors 中。后面用于抛出异常
					if (ambiguousConstructors == null) {
						ambiguousConstructors = new LinkedHashSet<>();
						ambiguousConstructors.add(constructorToUse);
					}
					ambiguousConstructors.add(candidate);
				}
			}
			// 如果 constructorToUse  构造函数为  null,则查找构造函数失败,抛出异常
			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)");
			}
			// 如果ambiguousConstructors 不为空说明有多个构造函数可适配,并且 如果不允许多个存在,则抛出异常
			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);
			}
			// 将解析的构造函数加入缓存
			if (explicitArgs == null) {
				argsHolderToUse.storeCache(mbd, constructorToUse);
			}
		}

		try {
			final InstantiationStrategy strategy = beanFactory.getInstantiationStrategy();
			Object beanInstance;

			if (System.getSecurityManager() != null) {
				final Constructor<?> ctorToUse = constructorToUse;
				final Object[] argumentsToUse = argsToUse;
				beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
						strategy.instantiate(mbd, beanName, beanFactory, ctorToUse, argumentsToUse),
						beanFactory.getAccessControlContext());
			}
			else {
				beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
			}
			// 将构建的实例加入BeanWrapper 中
			bw.setBeanInstance(beanInstance);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean instantiation via constructor failed", ex);
		}

这一步的目的就是根据参数数量和参数列表来选择最合适的构造函数,并且调用instantiate(beanName, mbd, constructorToUse, argsToUse) 方法来创建bean实例。

下面提三点:

  1. 由于在配置文件中声明bean不仅仅可以使用参数位置索引的方式创建,也支持通过参数名称设定参数值的情况,如下:
  <constructor-arg name="constructorDemoB" ref="constructorDemoB"></constructor-arg>

所以这时候,就需要首先确定构造函数中的参数名称。而获取参数名的方式有两种,一种是通过注解直接获取(@ConstructorProperties注解获取),即上面代码中对应的 ConstructorPropertiesChecker.evaluate(candidate, parameterCount);,另一种是通过Spring同构的工具类ParameterNameDiscoverer,这个在代码中也有使用。
完成这一步的时候,构造函数、参数名称、参数类型、参数值都确定后就可以锁定构造函数以及转换对应的参数类型了。
2. instantiate方法也很简单,根据beanFactory中的 bean实例化策略来实例化对象

	private Object instantiate(
			String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) {

		try {
			// 获取实例化策略
			InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
			// 通过策略实例化bean
			if (System.getSecurityManager() != null) {
				return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
						strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),
						this.beanFactory.getAccessControlContext());
			}
			else {
				return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean instantiation via constructor failed", ex);
		}
	}

注:关于 实例化策略,主要两种SimpleInstantiationStrategyCglibSubclassingInstantiationStrategy,简单实例化策略(直接反射) 和 Cglib 动态代理策略(通过cglib 代理),默认第二种。

  1. 在这里将解析后的内容添加到缓存中的代码如下:
	public void storeCache(RootBeanDefinition mbd, Executable constructorOrFactoryMethod) {
		synchronized (mbd.constructorArgumentLock) {
			// 保存工厂方法
			mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
			// 设置已经完全解析
			mbd.constructorArgumentsResolved = true;
			// 如果必须解析,将一些准备解析的参数保存,后面解析
			if (this.resolveNecessary) {
				mbd.preparedConstructorArguments = this.preparedArguments;
			}
			else {
				mbd.resolvedConstructorArguments = this.arguments;
			}
		}
	}

5. 无参构造函数实例化 - instantiateBean

相较于上面的有参构造函数,无参构造函数的解析显的那么简单
AbstractAutowireCapableBeanFactory#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 {
				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);
		}
	}

可以看到,最关键的调用代码是在InstantiationStrategy#instantiate(org.springframework.beans.factory.support.RootBeanDefinition, java.lang.String, org.springframework.beans.factory.BeanFactory)中,其细代码如下:

@Override
	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
		// Don't override the class with CGLIB if no overrides.
		// 如果当前bean中的方法没有都没有被重写,则直接反射就好了。不需要使用cglib 来进行代理
		if (!bd.hasMethodOverrides()) {
			Constructor<?> constructorToUse;
			// 尝试获取已经解析成功缓存的 构造函数
			synchronized (bd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse == null) {
					// 没有缓存则自己指定无参构造函数
					final Class<?> clazz = bd.getBeanClass();
					// 如果是接口直接抛出异常
					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 {
							// 返回符合参数类型的构造函数(这里是无参构造函数,所以并没有传递参数)
							constructorToUse = clazz.getDeclaredConstructor();
						}
						// 指定无参构造函数
						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 动态代理
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}
  • getDeclaredConstructor(Class<?>… parameterTypes) : 这种方法会返回制定參数类型的全部构造器,包含public的和非public的,当然也包含private的。

  • getDeclaredConstructors() : 的返回结果就没有參数类型的过滤了。

  • getConstructor(Class<?>… parameterTypes) : 这种方法返回的是上面那个方法返回结果的子集。仅仅返回制定參数类型訪问权限是public的构造器。

  • getConstructors() : 的返回结果相同也没有參数类型的过滤。

这里的逻辑非常简单, 甚至可以用一句话概括 : 是否有方法被覆盖(是否使用replacelookup进行配置),有则使用cglib动态代理,增强方法,否则直接通过反射创建。这一块判断是否方法被重写,不是为了事务或者aop,因为解析还没到那一步,这里是为了lookup-methodreplaced-method

6. 构造函数的筛选

在bean第一次创建的时候,并不存在构造缓存,所以会执行下面的代码。也就是说,这里是Bean第一次创建所调用的代码。

		// 6. 根据参数解析构造函数,并将解析出来的构造函数缓存到mdb的resolvedConstructorOrFactoryMethod属性中
		// 到这一步,说明 bean 是第一次加载,所以没有对构造函数进行相关缓存(resolved 为 false)
		// 调用 determineConstructorsFromBeanPostProcessors方法来获取指定的构造函数列表。
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		// 有候选构造函数 || 构造方式为构造注入 || 有构造函数入参 || 用于构造函数或工厂方法调用的显式参数args 不为null
		// 则调用 autowireConstructor 方法
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			return autowireConstructor(beanName, mbd, ctors, args);
		}

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

这里可以看到,如果没有进行任何额外的配置的话,会使用默认的方式(instantiateBean(beanName, mbd))创建bean。

我们这里整理一下调用autowireConstructor方法的条件(以下条件满足其一即可):

  • ctors != null :determineConstructorsFromBeanPostProcessors方法筛选出的候选构造函数不为null。对于默认的Spring来说,实际返回的是 AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors方法的返回值。而其作用简单来说就是返回被@Autowired注解修饰的构造函数(实际要更为复杂,这里可以简单这样理解),如下:

  • 在这里插入图片描述

  • mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR:这里的配置是通过xml 来配置bean时指定的装配方式,如果指定了构造装配,则调用autowireConstructor方法。如下:
    在这里插入图片描述

  • mbd.hasConstructorArgumentValues() :这里表示是否给当前bean定义了构造函数入参。通过xml配置bean的时候可以通过constructor-arg标签指定构造函数入参。如下
    -

  • !ObjectUtils.isEmpty(args) : 在通过getBean方法以编程方式传递的参数值args。如果有,使用其作为bean创建时构造函数的参数。

  • mbd.getPreferredConstructors() != null : RootBeanDefinition的实现是 null 。这里仅在GenericApplicationContext.ClassDerivedBeanDefinition中有过解析。
    关于determineConstructorsFromBeanPostProcessors方法,实际返回的是 AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors方法的返回值。

四、 总结

AbstractAutowireCapableBeanFactory#createBeanInstance方法处于Spring 创建bean 的入口阶段,完成了bean 的初步创建,调用各种扩展接口来尝试完成bean的创建(Supplier、factory-method),失败了则根据传入参数和和构造函数列表来选择合适的构造函数来创建bean。

但是并未完成属性注入、接口特性实现(如 Aware)、标签设置(如inti-method)的设置。在后续的 AbstractAutowireCapableBeanFactory#populateBean方法中完成了属性的注入。

需要注意的是,当一个bean第一次被解析时判断调用autowireConstructor方法来进行创建的时候,那么后面再次解析该bean仍会通过autowireConstructor方法进行解析。因为 autowireConstructor方法中在添加缓存的时候将constructorArgumentsResolved置为true来确保下一次解析时仍调用autowireConstructor方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/33098.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Eolink自动全代码注释自动上传API

目录 一、自动全代码注释 测试环境 Eolink Apikit安装 1、自建bootstrap项目用作测试 2、点击【File】->【Settings...】 3、搜索并安装【Eollink ApiKit】 4、添加eo注释 5、注释效果 二、一键上传API 1、配置服务信息 2、Server获取 3、SpaceKey获取 4、Proj…

C++回溯法leetcode练习集

文章目录什么是回溯法回溯法的模板组合组合总和|||洛谷刷题-八皇后问题题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1提示解析&#xff1a;电话号码的字母组合组合总和组合总和II分割回文串复原IP地址小结子集子集||递增子序列全排列全排列||842排列数字皇后问题什么…

BGP进阶:BGP 综合实验一

BGP路由优选规则 BGP是一个应用非常广泛的边界网关路由协议&#xff0c;被部署于大型的网络环境中。它能够支持大规模的网络&#xff0c;能够运载IP骨干网络中大批量的路由前缀并且在AS之间灵活的传递。BGP拥有丰富的路径属性&#xff0c;以及路由策略部署工具&#xff0c;正是…

win10家庭版安装Docker

首先查看你的电脑里面是否是win10且没有Hyper-V&#xff0c;是的话&#xff0c;那这个教程就是给你的啦~ 1、安装Hyper-v 首先将下面的内容复制到新建的txt中&#xff0c;将txt更名为Hyper-V.cmd,右键管理员运行这个文件 pushd "%~dp0"dir /b %SystemRoot%\servici…

为了提前预测比赛结果,于是我用Python获取比赛球员数据进行分析,结果...

为了提前预测比赛结果&#xff0c;于是我用Python获取比赛球员数据进行分析&#xff0c;结果...前因后果准备工作实现步骤代码展示部分效果展示最后前因后果 最近不是世界杯嘛&#xff0c;但是太忙了实在没时间看&#xff0c;于是为了凑热闹&#xff0c;用Python把本次球员信息…

AQS源码解析 5.Condition条件队列 await() signal() 核心方法

AQS源码解析—Condition条件队列 await() & signal() 核心方法 简介 在 Condition 条件队列中使用的也是 AQS 中的 Node 结构&#xff0c;它并没有使用 prev 和 next 属性&#xff0c;而使用的是 nextWaiter 去实现了一个单向链表的结构&#xff1a; Node nextWaiter;流…

MySQL索引和事务

目录 1.索引 1.1 索引的作用 1.2 查看索引 1.3 创建索引 1.4 删除索引 1.5 索引背后的数据结构(重点、面试题) 2.事务 2.1 什么是事务? 2.2 事务的使用 2.2.1 回滚 2.2.2 执行 2.3 事务的原子性(事务的初心) 2.4 事务的一致性 2.5 事务的持久性 2.6 事务的隔离性…

STM32之蜂鸣器实验

本章知识点 STM32GPIO的应用 蜂鸣器的原理&#xff08;最好网上看看&#xff09; 蜂鸣器概述 蜂鸣器是一种一体化结构的电子讯响器&#xff0c;采用直流电压供电&#xff0c;广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作…

CFD基本概念

1、流动控制方程 2、流体力学中的流动模型及流场解 N-S方程→&#xff08;忽略粘性与热扩散&#xff09;→Euler方程→&#xff08;无旋&#xff09;→全速位方程→&#xff08;小扰动&#xff09;→小扰动方程→&#xff08;不可压&#xff09;→labplace方程&#xff1b; 数…

【机器学习】python实现随机森林

目录 一、模型介绍 1. 集成学习 2. bagging 3. 随机森林算法 二、随机森林算法优缺点 三、代码实现 四、疑问 五、总结 本文使用mnist数据集&#xff0c;进行随机森林算法。 一、模型介绍 1. 集成学习 集成学习通过训练学习出多个估计器&#xff0c;当需要预测时通过…

[附源码]SSM计算机毕业设计流浪动物救助网站JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【百度AI_人脸识别】图片对比相似度、人脸对比登录(调摄像头)

人脸对比 此文档功能&#xff1a; 两张人脸图片相似度对比&#xff1a;比对两张图片中人脸的相似度&#xff0c;并返回相似度分值。存档一张图片与调用的摄像中的人脸进行对比。项目、资源下载&#xff1a;https://download.csdn.net/download/m0_70083523/87150842?spm1001.2…

编译原理—语法制导翻译、S属性、L属性、自上而下、自下而上计算

编译原理—语法制导翻译、S属性、L属性、自上而下、自下而上计算1.语法制导翻译1.1属性文法1.2算术表达式的计数器1.3属性的分类1.4属性依赖图继承属性的计算1.5语义规则的计算方法1.6属性计算次序2. S属性定义2.1 语法树与分析树2.2 语法树与DAG2.2.1构造表达式的语法树(DAG)2…

Android中常见的那些内存泄漏——【问题分析+方案】

1.静态Activity(Activity上下文Context)和View 静态变量Activity和View会导致内存泄漏&#xff0c;在下面代码中对Activity的Context和TextView设置为静态对象&#xff0c;从而产生内存泄漏&#xff1b; public class MemoryTestActivity extends AppCompatActivity {private…

[附源码]SSM计算机毕业设计健身健康规划系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

noexcept说明符/运算符

一、noexcept说明符 1、语法 &#xff08;1&#xff09;noexcept 与 noexcept(true) 相同 &#xff08;2&#xff09;noexcept&#xff08;表达式&#xff09; 如果 表达式 求值为 true&#xff0c;那么声明函数不会抛出任何异常。 &#xff08;3&#xff09;throw() //c1…

Ubuntu配置FTP服务

参考目录1.安装FTP服务器软件2.配置FTP服务3.Ubuntud登录ftp服务器4.windows下通过cuteFTPlianjei1.安装FTP服务器软件 (1) FTP文件传送协议(File Transfer Protocol&#xff0c;简称FTP)&#xff0c;是一个用于从一台主机到另一台主机传输文件的协议。 (2&#xff09;Linux下有…

Jetpack 之 LiveData 实现事件总线

事件总线相信大家很多时候都会用到&#xff0c;那大家常用的也就是常青树 EventBus&#xff0c;以及 RxJava 流行起来的后起之秀 RxBus。它们的使用方式都差不多&#xff0c;思想也都是基于观察者模式&#xff0c;正好 LiveData 的核心思想也是观察者模式&#xff0c;因此我们完…

做Android 开发这么久,还不明白 Android Framework 知识重要性?

Framework作为Android的框架层&#xff0c;为App提供了很多API调用&#xff0c;但很多机制都是Framework包装好后直接给App用的&#xff0c;如果不懂这些机制的原理&#xff0c;就很难在这基础上进行优化。 从做Android的第一天起&#xff0c;你一定听过无数次关于Framework的…

计算机音乐-乐理知识(1)

一、节拍 节拍&#xff08;Beat/Meter&#xff09;&#xff0c;是一个衡量节奏的单位&#xff0c;在音乐中&#xff0c;有一定强弱分别的一系列拍子在每隔一定时间重复出现。如 2 / 4 、 4 / 4 、 3 / 4 拍等。节拍&#xff0c;乐曲中表示固定单位时值和强弱规律的组织形式。 …