Spring 构造器推断模型源码分析

前言:
大家都熟悉Spring的 IOCbean实例化 工作过程,那么当一个bean有多个构造器,Spring会在 IOCbean实例化 过程中选择哪一个最终作为创建bean实例的合格的构造器 呢?这涉及到了Spring的构造器推断的源码部分。

整体框架

  • 关键词:
  • Spring推断结论:
  • 如何设置为自动装配?
  • 源码及解析:
    • createBean() 源码分析
    • determineConstructorsFromBeanPostProcessors() 源码分析
    • autowireConstructor()自动装配源码:
  • Q & A:
    • Q1. 手动装配指什么?
    • Q2. Spring 创建bean有哪些方式?
    • Q3. Spring自动装配中选择入参个数最多的构造器具体含义?
    • Q4. Spring在自动装配前期会计算最小入参个数,那么大于个数的入参具体值从哪里得知?

关键词:

  • 默认构造器
  • 注入模型
  • 手动装配
  • 自动装配
  • 合成构造方法
  • 标准构造方法
  • 合格构造方法
  • 默认构造器(defaultConstructor)
  • 必须构造器(requiredConstructor)

Spring推断结论:

从不同bean情形下的Spring的构造器推断结果,来进一步根据源码去分析过程

整个装配过程会依据不同的注入模型,注入模型的设置不是全局的,是每个bean可以在DeanDefinition中单独设置的:

  • 自动注入:构造方法的自动注入
  • AUTOWIRE_NO:默认,即手动装配

其他模式同AUTOWIRE_NO,为AUTOWIRE_NO模式和其他非自动注入模式的分析结果是一致的

手动装配 自动装配
只有一个无参构造器 手动装配为null,不会走自动装配,直接反射默认构造器 不走
只有一个有参构造器 手动装配返回该有参构造器(别无它选) 走,直接创建返回bean
只有一个@Autowired注解的构造器 返回该必须构造器 走,必须构造器创建bean
有多个@Autowired注解,required均为true 推断报错 不走,报错
有多个@Autowired注解,只有一个required=true 推断返回为true的这个构造器 走,用推断的构造器创建bean
有多个@Autowired注解,required均为false 手动装配返回@Autowired注解的构造器集合 走,选择最优的一个构造器创建bean
有一个无参构造器 + 多个有参构造器 手动装配结果为null,最终反射默认构造器 不走
多个有参构造器 手动装配结果为null,默认模式最终抛异常”未发现默认构造器“ 若默认注入模式,不走;若自动装配注入模式,选择入参个数最多的构造器创建bean
没有提供构造器 手动装配为null,默认模式下最终会调用编译器自动生成的构造器 自动装配模式下走,最终调用自动生成的构造器创建bean

多个有参构造器的情况,我们注意到在默认AUTOWIRE_NO注入模式下,Spring是会提示报错的。因为此种情况下Spring无法为多个模棱两可的构造器进行选择。

总结:

  • 自动装配只要在手动装配集合不返回空时,就会继续走自动装配
  • 手动装配是无论选择什么注入模式都会执行的,自动装配是不一定走的要根据手动装配的结果判定。但如果选择了自动注入那么就才一定走自动装配
  • 手动装配和自动装配的关系,不是非此即彼,而是顺序的。先手动装配,成功了继续自动装配,否则直接手动装配结束就完成了
  • 自动装配执行条件:1. 手动装配推断集合非空;2. 该bean注入模式为自动装配

如何设置为自动装配?


@Component
public class Person {

    public Person() {
    }

    public Person(Car car) {
    System.out.println("1");
    }

    public Person(Car car, House house) {
    System.out.println("2");
    }
}



@Component
public class LocalBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        GenericBeanDefinition person = ((GenericBeanDefinition) beanFactory.getBeanDefinition("person"));
        person.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
    }
}


  • 这里只是将person的BeanDefinition的AutowireMode 注入模式设置为AUTOWIRE_CONSTRUCTOR,不影响其他的bean的注入模式。其他bean的注入模式依然为默认的 AUTOWIRE_NO

源码及解析:

createBean() 源码分析

createBean() 中核心的创建源码是createBeanInstance(),所有的首次bean的创建都要走这个方法。
第二次bean创建时,如果单例,就不会进入到createBeanInstance()方法之前就会已经从一级或三级缓存中拿到对象;如果是原型,第二次也是会进入到createBeanInstance()方法的。


protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
		// Make sure bean class is actually resolved at this point.
		Class beanClass = resolveBeanClass(mbd, beanName);

		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}

		if (mbd.getFactoryMethodName() != null)  {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

/** 当第二次再来创建bean时,这里可以有个快捷方式,直接用第一次推断的结果进行创建
* 可从 BeanDefinition的 resolvedConstructorOrFactoryMethod 属性直接获取最终选择的一个合格的构造器
* 
*/
		// Shortcut when re-creating the same bean...
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		if (resolved) {
			if (autowireNecessary) {
			//这里进去可以看到用mbd.resolvedConstructorOrFactoryMethod 来直接创建bean
				return autowireConstructor(beanName, mbd, null, null);   
			}
			else {
				return instantiateBean(beanName, mbd);
			}
		}

/** 二者关系:
*  `determineConstructorsFromBeanPostProcessors()` :选择出合格的构造器的集合
* `autowireConstructor()` :
* 		1)从合格的构造器集合中选出一个
* 		2)集合为空 & 设置自动装配模式:Spring自动装配选择一个构造器返回
*/

		// Need to determine the constructor...
		Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);  //  `determineConstructorsFromBeanPostProcessors()` 具体逻辑后面源码分析

	/** 进入 `autowireConstructor()` 自动装配的条件
	*	1. ctors手动装配返回1个以上构造器
	*	2. 当前创建bean的BeanDefinition设置的注入模式为AUTOWIRE_CONSTRUCTOR自动装配
	*	3. args 不为空:根据args的类型匹配进行自动装配选择合格构造器
	*/
		if (ctors != null ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.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);
	}


  • 重点在 determineConstructorsFromBeanPostProcessors() 方法和 autowireConstructor() 方法
  • determineConstructorsFromBeanPostProcessors() 就是手动装配部分源码
  • autowireConstructor() 是自动装配部分源码

determineConstructorsFromBeanPostProcessors() 源码分析

核心就是进入到相关匹配的具体的的BeanPostProcessor去执行该接口的实现方法:


protected Constructor[] determineConstructorsFromBeanPostProcessors(Class beanClass, String beanName)
			throws BeansException {

// 最终会进入到 AutowiredAnnotationBeanPostProcessor 的determineCandidateConstructors()方法进行构造器推断,其他的BeanPostProcessor 并不关心这个接口,所以这里不需要关心
		if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					Constructor[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
					if (ctors != null) {
						return ctors;
					}
				}
			}
		}
		return null;
	}


//AutowiredAnnotationBeanPostProcessor类:

public Constructor[] determineCandidateConstructors(Class beanClass, final String beanName)
			throws BeanCreationException {

// 判断bean方法上是否有@LookUp注解,这里做个检查并缓存匹配的结果。这里可以作为了解
		// Let's check for lookup methods here..
		if (!this.lookupMethodsChecked.contains(beanName)) {
			try {
				ReflectionUtils.doWithMethods(beanClass, method -> {
					Lookup lookup = method.getAnnotation(Lookup.class);
					if (lookup != null) {
						Assert.state(this.beanFactory != null, "No BeanFactory available");
						LookupOverride override = new LookupOverride(method, lookup.value());
						try {
							RootBeanDefinition mbd = (RootBeanDefinition) this.beanFactory.getMergedBeanDefinition(beanName);
							mbd.getMethodOverrides().addOverride(override);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(beanName,
									"Cannot apply @Lookup to beans without corresponding bean definition");
						}
					}
				});
			}
			catch (IllegalStateException ex) {
				throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
			}
			this.lookupMethodsChecked.add(beanName);
		}


/** 
* this.candidateConstructorsCache:缓存类的所有合格的构造器
* 因为Spring认为解析出bean的合格的构造器是个耗时的过程
*/
		// Quick check on the concurrent map first, with minimal locking.
		Constructor[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
		if (candidateConstructors == null) {
			// Fully synchronized resolution now...
			// 同步 this.candidateConstructorsCache 缓存
			synchronized (this.candidateConstructorsCache) {
				candidateConstructors = this.candidateConstructorsCache.get(beanClass);
				if (candidateConstructors == null) {
					Constructor[] rawCandidates;
					try {
						rawCandidates = beanClass.getDeclaredConstructors();
					}
					catch (Throwable ex) {
						throw new BeanCreationException(beanName,
								"Resolution of declared constructors on bean Class [" + beanClass.getName() +
								"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
					}
					List> candidates = new ArrayList<>(rawCandidates.length);
					Constructor requiredConstructor = null;   // 必须构造器
					Constructor defaultConstructor = null;   // 默认构造器
					Constructor primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);  // 指Kotlin查找的构造器
					int nonSyntheticConstructors = 0;
					for (Constructor candidate : rawCandidates) {
						if (!candidate.isSynthetic()) {
							nonSyntheticConstructors++;
						}
						else if (primaryConstructor != null) {
							continue;
						}
						AnnotationAttributes ann = findAutowiredAnnotation(candidate);
						if (ann == null) {
							Class userClass = ClassUtils.getUserClass(beanClass);
							if (userClass != beanClass) {
								try {
									Constructor superCtor =
											userClass.getDeclaredConstructor(candidate.getParameterTypes());
									ann = findAutowiredAnnotation(superCtor);
								}
								catch (NoSuchMethodException ex) {
									// Simply proceed, no equivalent superclass constructor found...
								}
							}
						}
						if (ann != null) {
							if (requiredConstructor != null) {
								throw new BeanCreationException(beanName,
										"Invalid autowire-marked constructor: " + candidate +
										". Found constructor with 'required' Autowired annotation already: " +
										requiredConstructor);
							}
							boolean required = determineRequiredStatus(ann);
							if (required) {
								if (!candidates.isEmpty()) {
									throw new BeanCreationException(beanName,
											"Invalid autowire-marked constructors: " + candidates +
											". Found constructor with 'required' Autowired annotation: " +
											candidate);
								}
								requiredConstructor = candidate;
							}
							candidates.add(candidate);
						}
						else if (candidate.getParameterCount() == 0) {
							defaultConstructor = candidate;
						}
					}
					if (!candidates.isEmpty()) {
						// Add default constructor to list of optional constructors, as fallback.
						if (requiredConstructor == null) {
							if (defaultConstructor != null) {
								candidates.add(defaultConstructor);
							}
							else if (candidates.size() == 1 && logger.isInfoEnabled()) {
								logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
										"': single autowire-marked constructor flagged as optional - " +
										"this constructor is effectively required since there is no " +
										"default constructor to fall back to: " + candidates.get(0));
							}
						}
						candidateConstructors = candidates.toArray(new Constructor[0]);
					}
					else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
						candidateConstructors = new Constructor[] {rawCandidates[0]};
					}
					else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
							defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
						candidateConstructors = new Constructor[] {primaryConstructor, defaultConstructor};
					}
					else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
						candidateConstructors = new Constructor[] {primaryConstructor};
					}
					else {
						candidateConstructors = new Constructor[0];
					}
					this.candidateConstructorsCache.put(beanClass, candidateConstructors);
				}
			}
		}
		return (candidateConstructors.length > 0 ? candidateConstructors : null);
	}





autowireConstructor()自动装配源码:


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;  // 最终args包装对象
		Object[] argsToUse = null;   // 从argsToUser 再转化到 ArgumentsHolder 对象

		 // explicitArgs 可以作为扩展点,直接赋值要使用的args,一般都为null
		if (explicitArgs != null) { 
			argsToUse = explicitArgs;
		}
		/** 两件事:
		* 1. 是否 唯一选定构造器、args 已经被解析出来了,若已被解析出来则该bean的RootBeanDefinition中相应属性非空
		* 2. 解析 preparedConstructorArguments 给 argsToUse:这里会对 等BeanDefinition属性进行适当的类型转换等操作,才是Spring需要的最终的args 的类型
		* (类型转换后会将args会从 preparedConstructorArguments 转到 resolvedConstructorArguments 中)
		*/
		else {
			Object[] argsToResolve = null;
			synchronized (mbd.constructorArgumentLock) {
				constructorToUse = (Constructor) mbd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse != null && mbd.constructorArgumentsResolved) {
					// Found a cached constructor...
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			 // PreparedArguments 在赋值给argsToUse会进行相应的类型转换
			 // 因为:一种情况就是value可能是类的全限定类名是个String类型,但需要转化为相应的类对象
			if (argsToResolve != null) {
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
			}
		}

		/** 这里才开始真正的自动装配逻辑:
		*
		*/
		if (constructorToUse == null || argsToUse == null) {   // 只要有一个成立即可,因为可能是默认的无参构造器
			// Take specified constructors, if any.
			/**  这里先拿到手动装配可用的构造器集合 chosenCtors,chosenCtors集合根据值分为三种情况:
			* 1. null,三种情况:
			* 		1). 没有构造器;2). 只有一个无参构造器;3). 多个构造器
			* 2. size=1
			* 3. size > 1
			* 下面分别对每种情况进行处理。
			*/
			Constructor[] candidates = chosenCtors;  
			/** 情况一: null
			*  拿到所有的构造器,没有public就拿private的
			*/
			if (candidates == null) {
				Class beanClass = mbd.getBeanClass();
				try {
					candidates = (mbd.isNonPublicAccessAllowed() ?
							beanClass.getDeclaredConstructors() : beanClass.getConstructors());
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Resolution of declared constructors on bean Class [" + beanClass.getName() +
							"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
				}
			}

			/** 情况二: size=1
			*  满足以下3个条件的只有:默认构造器
			*  默认构造器反射创建bean返回
			*/
			if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {  // 没有引入
				Constructor uniqueCandidate = candidates[0];
				if (uniqueCandidate.getParameterCount() == 0) {
					synchronized (mbd.constructorArgumentLock) {
						mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;  // 构造器选定赋值RootBeanDefinition
						mbd.constructorArgumentsResolved = true; // args 已解析true标志
						mbd.resolvedConstructorArguments = EMPTY_ARGS; // 默认构造器所有是空args
					}
					bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));  // instantiate() 反射生成bean实例
					return bw;  //返回其BeanWrapper对象
				}
			}

			/** 情况三: size>1
			*  
			*/
			// Need to resolve the constructor.
			// autowiring 表示是否需要自动注入
			boolean autowiring = (chosenCtors != null ||
					mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
			ConstructorArgumentValues resolvedValues = null;

			/** minNrOfArgs 表示Spring选择的构造器允许的入参个数最小值,即就是将来选择的构造器的入参长度一定要 >= minNrOfArgs才可以
			* 值具体确定,两种情况:
			* 一、explicitArgs非空: minNrOfArgs = explicitArgs个数
			* 二、其他:minNrOfArgs = ConstructorArgumentValues个数。(程序员自定义的构造器入参个数)
			*/
			int minNrOfArgs;
			if (explicitArgs != null) {
				minNrOfArgs = explicitArgs.length;
			}
			else {
				ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
				resolvedValues = new ConstructorArgumentValues();
				// 对ConstructorArgumentValues进行解析 和 个数统计
				// 并将 RootBeanDefinition 中的ConstructorArgumentValues 解析后放到resolvedValues中以备后续留用
				minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
			}

		
			/** sortConstructors() 非常重要:对所有的候选构造器进行排序,排序原则:
			*  按照构造器修饰符:public、protected、default、private
			*  按照入参个数:
			*  按照参数精准程度:比如相同修饰符、相同入参长度的构造器,同一个位置的参数,类型更加准确的构造器排序在前
			*/
			AutowireUtils.sortConstructors(candidates);
			// 到这里,candidates是经过排序的构造器集合
			// 最小差异权重,“最小”?Spring认为差异最小的参数类型是更合适的
			int minTypeDiffWeight = Integer.MAX_VALUE;
			Set> ambiguousConstructors = null;  // 模糊不清的构造器集合
			LinkedList causes = null;

			for (Constructor candidate : candidates) {
				Class[] paramTypes = candidate.getParameterTypes();

				// 如果 constructorToUse 非空选择出了构造器,那么直接结束循环
				if (constructorToUse != null && argsToUse != 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;
				}
				// 如果入参长度 < minNrOfArgs,说明当前构造器不符合我们的要求循环下一个构造器
				if (paramTypes.length < minNrOfArgs) {
					continue;
				}

				ArgumentsHolder argsHolder;
				if (resolvedValues != null) {
					try {
						// 得到当前构造器的参数名字集合:paramNames
						String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
						if (paramNames == null) {
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
							if (pnd != null) {
								paramNames = pnd.getParameterNames(candidate);
							}
						}
						
						/** 得到 argsHolder,就是具体的 args值的封装,包含三部分:
						* rawArguments、arguments、preparedArguments
						* 这里作用:将 args 根据参数类型实例化 或 直接从IOC中获取到bean
						* (这里可能会处理bean的循环依赖的问题)
						*/
						argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
								getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
					}
					catch (UnsatisfiedDependencyException ex) {
						if (logger.isTraceEnabled()) {
							logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
						}
						// Swallow and try next constructor.
						if (causes == null) {
							causes = new LinkedList<>();
						}
						causes.add(ex);
						continue;
					}
				}
				else {
					// Explicit arguments given -> arguments length must match exactly.
					if (paramTypes.length != explicitArgs.length) {
						continue;
					}
					argsHolder = new ArgumentsHolder(explicitArgs);
				}

				/** 计算差异:argsHolder 和 paramTypes 之间的差异
				* 差异值,每个构造器都会计算出一个差异值,即就是入参具体值 和 构造器本身的入参类型之间是否更匹配、更相近
				* Spring认为,差异越小的,越是匹配。故最终只选择 diff 最小的那一个构造器
				*/
				// typeDiffWeight = 具体的差异值
				int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
						argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
				// Choose this constructor if it represents the closest match.
				
				/** 替换最小的差异值及其 constructorToUse 作为最新的 选择构造器
				*
				*/
				if (typeDiffWeight < minTypeDiffWeight) {
					constructorToUse = candidate;  // 更新 constructorToUse
					argsHolderToUse = argsHolder;  //更新 argsHolderToUse
					argsToUse = argsHolder.arguments;
					minTypeDiffWeight = typeDiffWeight;
					ambiguousConstructors = null;  // 置空ambiguousConstructors,有了更合适的构造器,模糊不清的集合当然就为空啦
				}
				/** 
				*
				*/
				else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
					if (ambiguousConstructors == null) {
						ambiguousConstructors = new LinkedHashSet<>();
						ambiguousConstructors.add(constructorToUse);
					}
					ambiguousConstructors.add(candidate);
				}
			}

			/** 异常解决:最终 “构造器选择” 还是没有被确定
			* 一般就是如下两种原因:
			*  1. 不能匹配:Could not matching constructor
			*  2.有模糊不清的构造器存在:例如入参长度相同、差异值相同的情况
			* (这两种异常,很多情况都是见到过的,就是这里抛出的)
			*/
			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);
			}

			if (explicitArgs == null && argsHolderToUse != null) {
				argsHolderToUse.storeCache(mbd, constructorToUse);
			}
		}

		Assert.state(argsToUse != null, "Unresolved constructor arguments");
		// 根据最终确定的构造器进行反射进行实例化,并返回bean实例封装对象
		bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
		return bw;
	}




总结:

  • 先确定 最小参数个数
  • 候选构造器的入参个数 < 最小参数个数,忽略
  • 对候选构造器进行排序,排序规则如上
  • ~~~~~以下进入已排序的候选构造器的循环~~~~~~
  • 入参具体值:找出所有的候选构造器在IOC中的具体的入参值
  • 入参具体值 vs 入参具体类型 之间的差异
  • ~~~~~最终,找到一个 “入参长度大于minNrOfArgs” & ”差异值最小“ 的构造器

这里就可以解释,为什么多个有参构造器 & 自动装配下,会使用入参个数最多的构造器?
在循环寻找构造器开始,会对候选构造器进行排序,排序规则决定了相同差异值情况下,肯定会优先使用入参个数最多的构造器

Q & A:

Q1. 手动装配指什么?

Spring在根据bean类的所有由程序员实现的构造器中选择最合格、最合理的一个构造器,本质还是程序员手动实现的只是Spring做一个合理的手动筛选,还并没有参与Spring自主选择的过程。

Q2. Spring 创建bean有哪些方式?

1. 反射
2. @Bean注解
3. FactoryBean类实现

Q3. Spring自动装配中选择入参个数最多的构造器具体含义?

Spring自动装配原则上是选择具有更多的入参个数的构造器越好,但要求入参一定要Spring可以从自己的IOC容器中获取到的入参才可以。所以,是Spring可以管理的入参类型中的所有构造器的个数最多的。

如果一个入参个数的构造器,其中有一个入参类型是Spring无法自动管理生成注入的,那么Spring不会推断该构造器。



Q4. Spring在自动装配前期会计算最小入参个数,那么大于个数的入参具体值从哪里得知?

从Spring的IOC容器中,或者Spring会自动的去调用beanFactory#getBean() 方法去创建需要的bean并自动注入


你可能感兴趣的:(java,spring,后端,spring,boot)