判断可否使用缓存中的构造器
// Shortcut when re-creating the same bean...// 标记是否有缓存的构造方法boolean resolved = false;// 缓存的构造器是否有参数,如果没有表示:需要自动匹配boolean autowireNecessary = false;// 如果没有参数if (args == null) {synchronized (mbd.constructorArgumentLock) {// 已经缓存的构造方法或者工厂方法(Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,// 避免再次创建相同bean时再次解析)if (mbd.resolvedConstructorOrFactoryMethod != null) {resolved = true;autowireNecessary = mbd.constructorArgumentsResolved;}}}// 表示有缓存的构造方法,利用已经解析好的构造方法去实例化对象if (resolved) {if (autowireNecessary) {// 构造器有参数,构造函数自动注入return autowireConstructor(beanName, mbd, null, null);} else {// 默认构造函数return instantiateBean(beanName, mbd);}}
从bean后置处理器中为自动装配寻找构造方法
// Candidate constructors for autowiring?// 从bean后置处理器中为自动装配寻找构造方法,比如:AutowiredAnnotationBeanPostProcessorConstructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);}
通过 determineConstructorsFromBeanPostProcessors 得到扩展的构造方法。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors 
@Nullableprotected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)throws BeansException {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;}
找出最合适的构造方法
ctors = mbd.getPreferredConstructors();if (ctors != null) {// 构造函数自动注入return autowireConstructor(beanName, mbd, ctors, null);}
🔥 autowireConstructor
上面的推断方式最终还是会走到这个方法,利用带参数的构造函数去实例化对象,是最复杂的一种,因为不确定太多。所以这块的代码相当的长了。
首先开发者可以通过什么方式来指定使用哪个构造方法呢?
https://www.jb51.net/article/264134.htm
- 通过xml中的
标签,这个标签表示构造方法参数,所以可以根据这个确定想要使用的构造方法的参数个数,从而确定想要使用的构造方法;  - 通过@Autowired注解,@Autowired注解可以写在构造方法上,所以哪个构造方法上写了@Autowired注解,表示开发者想使用哪个构造方法,当然,它和第一个方式的不同点是,通过xml的方式,我们直接指定了构造方法的参数值,而通过@Autowired注解的方式,需要Spring通过byType+byName的方式去找到符合条件的bean作为构造方法的参数值;
 - 如果Bean为注解@Lazy修饰的或者非单例的,可以通过getBean方法设置构造方法的入参,达到指定构造方法的效果。如,applicationContext.getBean(“BeanDemo”, new CircularRefA());【同理,获取beanDefinition,使用beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(new CircularRefA());指定构造方法参数】
 
接下来解析这块复杂的代码。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireConstructor
protected BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);}
org.springframework.beans.factory.support.ConstructorResolver#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;Object[] argsToUse = null;// 如果有构造函数的参数直接使用if (explicitArgs != null) {argsToUse = explicitArgs;} 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;}}}// 从缓存中得到了参数if (argsToResolve != null) {// 解析参数类型,比如 Student(int,int),通过此方法将参数从("1","1")转换成(1,1)argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);}}// 缓存中没有if (constructorToUse == null || argsToUse == null) {// Take specified constructors, if any.Constructor<?>[] candidates = chosenCtors;if (candidates == null) {// 如果参数没有给构造函数,那么尝试从定义中获取Class<?> beanClass = mbd.getBeanClass();try {candidates = (mbd.isNonPublicAccessAllowed() ? beanClass.getDeclaredConstructors() : beanClass.getConstructors());} catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Resolution of declared constructors on bean Class [" + beanClass.getName() +"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);}}// 如果只有一个构造函数,并且没有参数。那就是默认的构造函数了。if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {Constructor<?> uniqueCandidate = candidates[0];if (uniqueCandidate.getParameterCount() == 0) {synchronized (mbd.constructorArgumentLock) {mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;mbd.constructorArgumentsResolved = true;mbd.resolvedConstructorArguments = EMPTY_ARGS;}bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));return bw;}}// 判断是否需要自动装配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);}// 排序给定的构造函数,public构造函数优先参数数量降序、非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();// 如果 constructorToUse argsToUse 不空,并且 参数数量够用,就不用继续找了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) {continue;}ArgumentsHolder argsHolder;// 参数类型的数组Class<?>[] paramTypes = candidate.getParameterTypes();if (resolvedValues != null) {try {// 从注解上获取参数名称String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);if (paramNames == null) {// 获取配置的参数名称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);}// 如果是宽松模式就走方法getTypeDifferenceWeight;否则走getAssignabilityWeightint 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 on bean class [" + mbd.getBeanClassName() + "] " +"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");} else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {// 存在不能直接访问的构造函数,并且不是宽松的访问 ,那么异常throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Ambiguous constructor matches found on bean class [" + mbd.getBeanClassName() + "] " +"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +ambiguousConstructors);}// 解析得到的参数加入缓存if (explicitArgs == null && argsHolderToUse != null) {argsHolderToUse.storeCache(mbd, constructorToUse);}}// 实例化Assert.state(argsToUse != null, "Unresolved constructor arguments");bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));return bw;}
构造函数创建对象,最终都会来到这个方法,ConstructorResolver#autowireConstructor ,风格不像前面的套路,getBean、doGetBean、createBean、doCreateBean,都是 XX ,doXX,一层一层嵌套,比较容易理解。这个方法有点复杂,代码太长……
梳理下过程:
| 步骤 | 说明 | 
|---|---|
1. 确定构造函数的参数  | 
1. 如果 explicitArgs 参数不为空的话就可以直接使用该参数,因为这个参数是用户在 getBean 的时候指定的; 2. explicitArgs 为空,那么尝试去缓存中获取,缓存的格式不确定,所以需要用方法 resolvePreparedArguments 将参数转换 (比如:Student(int,int),通过此方法将参数从(“1”,”1”) 转换成(1,1) ) 3. 缓存中也没有的话,就去解析 BeanDefinition 。  | 
2. 确定构造函数  | 
采用参数个数和类型匹配的方式。 1. 同样如果参数没有构造函数,那么解析 BeanDefinition 得到; 2. 如果发现只有一个构造函数并且没有参数,可以确定是默认无参构造,可以直接实例化; 3. 解析 BeanDefinition 得到构造函数的参数信息,利用方法 resolveConstructorArguments 转换构造函数的参数类型 resolvedValues 和确定参数的个数 minNrOfArgs; 4. 给构造函数排个序( public 构造函数优先参数数量降序、非 public 构造函数参数数量降序); 5. 然后分别就每一个构造函数进行排查: 1. 参数个数比minNrOfArgs小,参数不够,排除; 2. 如果 resolvedValues 不为空,获取当前构造函数的参数名称,将结果放到 argsHolder;如果为空,并且 explicitArgs 不为空,那么将 explicitArgs 放到 argsHolder;否则继续找一个构造函数; 3. 得到当前构造函数的参数相关信息后,开始比对是否合适。如果是宽松对比模式那么对比类型 argsHolder.getTypeDifferenceWeight;否则对比 argsHolder.getAssignabilityWeight,得到一个差异值; 4. 得到的差异值和默认最小差异值对比,如果较小,那么当前构造函数就是可用的。否则记录相关信息到 ambiguousConstructors。  | 
3. 记录异常  | 
如果经过上一步,仍然没有找到合适的构造函数,那么打印相关信息。 | 
4. 实例化对象  | 
没有问题的话,根据构造函数及参数去实例化对象。 | 
确定构造函数的参数
// 如果有构造函数的参数直接使用if (explicitArgs != null) {argsToUse = explicitArgs;} 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;}}}// 从缓存中得到了参数if (argsToResolve != null) {// 解析参数类型,比如 Student(int,int),通过此方法将参数从("1","1")转换成(1,1)argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);}}
首先判断方法是否传递了参数 explicitArgs ,这个参数是通过代码指定的,并非从配置文件而来,所以如果这个参数存在的话,那么应该使用的构造函数和参数就是确定的,不用再解析了。
如果这个参数不存在的话,就去缓存找构造函数和参数,查询到需要对缓存的数据进行解析,通过方法 resolvePreparedArguments。查询不到的话就去解析 Beandefinition。
解析其实就是把 argsToResolve 解析到 argsToUse,如下所示:
argsToResolve = mbd.preparedConstructorArguments;
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
得到所有构造函数
有了参数之后,开始确定到底使用哪个构造函数。
同样构造函数可以通过方法传递进来,如果没有的话,那么也是从 BeanDefinition 缓存中获取(可能有多个)
如果判断只有一个构造函数,并且还没有参数,别无选择,只能使用这个唯一构造函数去实例化。
大多数情况下可能有多个构造函数:
得到构造函数的参数个数 minNrOfArgs。
int minNrOfArgs;if (explicitArgs != null) {minNrOfArgs = explicitArgs.length;} else {// 获取解析阶段得到的构造函数信息ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();resolvedValues = new ConstructorArgumentValues();// 解析构造器的参数和值,从而得到构造器使用最少参数的数量minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);}
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();  
这个是我们在 BeanDefinition 解析阶段解析标签得到的数据。系统默认标签解析-解析 constructor-arg 标签。
然后通过方法 resolveConstructorArguments 解析里面参数,将解析的结果放到 resolvedValues 中,同时统计了参数个数。
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();TypeConverter converter = (customConverter != null ? customConverter : bw);BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);// 参数数量的最小值,默认是按照索引配置的参数的数量 + 按照名称配置的参数的数量/*<bean id="pig" class="cn.lichenghao.createBeanInstance.entity.Pig"><constructor-arg name="id" value="红猪"></constructor-arg><constructor-arg index="1" value="222"></constructor-arg><constructor-arg index="2" value="222"></constructor-arg><constructor-arg index="3" value="222"></constructor-arg></bean>或者<bean id="pig" class="cn.lichenghao.createBeanInstance.entity.Pig"><constructor-arg index="0" value="222"></constructor-arg><constructor-arg index="1" value="222"></constructor-arg><constructor-arg name="age" value="111"></constructor-arg><constructor-arg index="3" value="222"></constructor-arg></bean>*/int minNrOfArgs = cargs.getArgumentCount(); //4// 遍历根据位置配置的参数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 + 1 > minNrOfArgs) {minNrOfArgs = index + 1;}// 参数的值没有转换的话,进行转换,记录在resolvedValues中ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();if (valueHolder.isConverted()) {resolvedValues.addIndexedArgumentValue(index, valueHolder);} else {Object resolvedValue =valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());ConstructorArgumentValues.ValueHolder resolvedValueHolder =new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());resolvedValueHolder.setSource(valueHolder);resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);}}for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {// 参数的值没有转换的话,进行转换,记录在resolvedValues中if (valueHolder.isConverted()) {resolvedValues.addGenericArgumentValue(valueHolder);} else {Object resolvedValue =valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());resolvedValueHolder.setSource(valueHolder);resolvedValues.addGenericArgumentValue(resolvedValueHolder);}}return minNrOfArgs;}
给构造函数排个序。
排序规则:public构造函数优先参数数量降序、非public构造函数参数数量降序。
AutowireUtils.sortConstructors(candidates);public static void sortConstructors(Constructor<?>[] constructors) {Arrays.sort(constructors, EXECUTABLE_COMPARATOR);}public static final Comparator<Executable> EXECUTABLE_COMPARATOR = (e1, e2) -> {int result = Boolean.compare(Modifier.isPublic(e2.getModifiers()), Modifier.isPublic(e1.getModifiers()));return result != 0 ? result : Integer.compare(e2.getParameterCount(), e1.getParameterCount());};
得到每个构造函数的参数信息
这一步会变量所有的构造函数,得到每个构造函数的参数相关信息。
for (Constructor<?> candidate : candidates) {........}
获取构造函数参数的数量 parameterCount,如果比 minNrOfArgs 还小,参数不够啊,继续找下一个;
int parameterCount = candidate.getParameterCount();// 参数比最小参数还小,不够用,继续找if (parameterCount < minNrOfArgs) {continue;}
判断 resolvedValues :
ArgumentsHolder argsHolder;// 参数类型的数组Class<?>[] paramTypes = candidate.getParameterTypes();if (resolvedValues != null) {try {// 从注解上获取参数名称String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);if (paramNames == null) {// 获取配置的参数名称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);}
分成不同的分支:
| 分支 | 说明 | 
|---|---|
| resolvedValues==null | 说明用户可能在 getBean 环节提供了构造函数的参数,那么判断下参数个数是否等于用户给定的 explicitArgs 参数个数,不等判断下一个构造函数;相等的话,就留下来,继续后面的对比。 | 
| resolvedValues==null && 没有提供相关 explicitArgs | 说明用户没有配置构造函数的参数,也就意味着后面的逻辑都不会走。直接都不用判断了,会直接走无参构造。 | 
| resolvedValues != null | 解析构造函数的参数名称。 | 
如果 resolvedValues != null 那么需要进一步解析得到当前构造函数的参数名称信息。有如下两种方式得到。
第一种方式:
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
利用注解的方式
@ConstructorProperties({“x”, “y”})
 public Point(int x, int y) {
           this.x = x;
           this.y = y;
}
org.springframework.beans.factory.support.ConstructorResolver.ConstructorPropertiesChecker
private static class ConstructorPropertiesChecker {@Nullablepublic static String[] evaluate(Constructor<?> candidate, int paramCount) {ConstructorProperties cp = candidate.getAnnotation(ConstructorProperties.class);if (cp != null) {String[] names = cp.value();if (names.length != paramCount) {throw new IllegalStateException("Constructor annotated with @ConstructorProperties but not " +"corresponding to actual number of parameters (" + paramCount + "): " + candidate);}return names;} else {return null;}}}
第二种方式:
直接解析构造函数中定义的参数名称。
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();if (pnd != null) {paramNames = pnd.getParameterNames(candidate);}
到此,先整理下,我们都得到了哪些信息:
- BeanDefinition 信息;
 - BeanWrapperImpl bean 包装对象;
 - resolvedValues,配置文件中配置的构造函数参数信息;
 - 当前构造函数参数的类型 paramTypes,如: [String,String];
 - 当前构造函数参数的名称 paramNames,如: [x,y];
 
将解析后的数据,利用 createArgumentArray 封装到 ArgumentsHolder ,然后继续下一步的判断。
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames, getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
其中方法 getUserDeclaredConstructor 用于判断 candidate 构造函数是否是 cglib 代码对象的构造函数,如果是的话,返回原始对象的构造函数。
protected Constructor<?> getUserDeclaredConstructor(Constructor<?> constructor) {// 获取构造函数对应的Class对象Class<?> declaringClass = constructor.getDeclaringClass();// 如果是 cglib 代理类,返回原始 ClassClass<?> userClass = ClassUtils.getUserClass(declaringClass);// 不等说明constructor是cglib代理类的构造函数if (userClass != declaringClass) {try {// 获取原始Class中的构造函数return userClass.getDeclaredConstructor(constructor.getParameterTypes());} catch (NoSuchMethodException ex) {// No equivalent constructor on user class (superclass)...// Let's proceed with the given constructor as we usually would.}}return constructor;}
那么继续进入方法 createArgumentArray .
对比构造函数是否满足
对比有两种模式,一种 lenientConstructorResolution = true 宽松模式, 另外一种是 lenientConstructorResolution = false,分别通过 getTypeDifferenceWeight 和 getAssignabilityWeight 计算出对应的差异值。
getTypeDifferenceWeight
比较参数值的类型。
public int getTypeDifferenceWeight(Class<?>[] paramTypes) {// If valid arguments found, determine type difference weight.// Try type difference weight on both the converted arguments and// the raw arguments. If the raw weight is better, use it.// Decrease raw weight by 1024 to prefer it over equal converted weight.int typeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.arguments);int rawTypeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.rawArguments) - 1024;return Math.min(rawTypeDiffWeight, typeDiffWeight);}
重载方法
org.springframework.util.MethodInvoker#getTypeDifferenceWeight
public static int getTypeDifferenceWeight(Class<?>[] paramTypes, Object[] args) {int result = 0;for (int i = 0; i < paramTypes.length; i++) {if (!ClassUtils.isAssignableValue(paramTypes[i], args[i])) {// 如果args[i]==null 并且 paramTypes[i] 是基本类型// 如果args[i]!=null 并且 args[i]不是paramTypes[i]同类,也不是子类// 说明不是空,就是类型根本一点边都不着return Integer.MAX_VALUE;}if (args[i] != null) {// 参数类型Class<?> paramType = paramTypes[i];// 参数值的父类Class<?> superClass = args[i].getClass().getSuperclass();while (superClass != null) {if (paramType.equals(superClass)) {result = result + 2;superClass = null;} else if (ClassUtils.isAssignable(paramType, superClass)) {result = result + 2;superClass = superClass.getSuperclass();} else {superClass = null;}}if (paramType.isInterface()) {result = result + 1;}}}return result;}
遍历参数类型,开始分析每个参数值。
第一种情况:
args[i]==null 并且 paramTypes[i] 是基本数据类型;那么直接返回 Integer.MAX_VALUE;
args[i]!=null 并且 args[i] 不是 paramTypes[i] 同类,也不是子类;
第二种情况 args[i]!=null
获取参数类型 Class<?> paramType = paramTypes[i];
获取参数值的父类型 Class<?> superClass = args[i].getClass().getSuperclass();
如果 superClass!=null ,开始循环判断当前参数值的每一个父类:
- 如果 paramType==superClass的话,那么匹配度+2,结束循环;
 - 如果 ClassUtils.isAssignable(paramType, superClass) 匹配度+2,继续比较该父类的父类,相当于一个父类就+2;
 - 如果以上都不满足,结束循环。
 
如果参数的类型为接口类型,那么匹配度+1。
依次比较每一个参数类型和参数值类型,最终得到 typeDiffWeight。
上面的文字描述感觉晕晕的,可以用一段代码来验证测试下。
假如我们有如下类:A extend B implements D ;B etend C
public class A extends B implements D {public static void main(String[] args) {Object[] myArgs = new Object[]{new A()};// 参数类型为A,完全匹配 0System.out.println(MethodInvoker.getTypeDifferenceWeight(new Class[]{A.class}, myArgs));// 参数类型为B,父类匹配 2System.out.println(MethodInvoker.getTypeDifferenceWeight(new Class[]{B.class}, myArgs));// 参数类型为C,父父匹配 4System.out.println(MethodInvoker.getTypeDifferenceWeight(new Class[]{C.class}, myArgs));// 参数类型为D,接口匹配 1System.out.println(MethodInvoker.getTypeDifferenceWeight(new Class[]{D.class}, myArgs));}}public class B extends C{}public class C {}public interface D {}
好,回到方法。分别用 arguments 和 rawArguments 做了比对。
这俩参数的区别:
arguments:参数类型是经过转换的,比如:xx(String,String) ——> xx(12(Integer),”122”(String))
rawArguments:原始的可能是 xx(String,String) 
public int getTypeDifferenceWeight(Class<?>[] paramTypes) {// If valid arguments found, determine type difference weight.// Try type difference weight on both the converted arguments and// the raw arguments. If the raw weight is better, use it.// Decrease raw weight by 1024 to prefer it over equal converted weight.int typeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.arguments);int rawTypeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.rawArguments) - 1024;return Math.min(rawTypeDiffWeight, typeDiffWeight);}
getAssignabilityWeight
public int getAssignabilityWeight(Class<?>[] paramTypes) {for (int i = 0; i < paramTypes.length; i++) {if (!ClassUtils.isAssignableValue(paramTypes[i], this.arguments[i])) {return Integer.MAX_VALUE;}}for (int i = 0; i < paramTypes.length; i++) {if (!ClassUtils.isAssignableValue(paramTypes[i], this.rawArguments[i])) {return Integer.MAX_VALUE - 512;}}return Integer.MAX_VALUE - 1024;}
这个方法就比上个看着简单多了,主要是利用了 ClassUtils.isAssignableValue 方法。参考:ClassUtil
对比权重结果
经过上面的比对得到的 typeDiffWeight 权重和 minTypeDiffWeight 对比。
比 minTypeDiffWeight 小的话那么就是符合的构造函数。记录对应的构造函数及相关参数。否则记录信息到 ambiguousConstructors 中。继续下一个构造函数的对比。
最终对比完毕后,并没有找到合适,那么就要记录相关信息。抛出异常 BeanCreationException 。
使用构造函数实例化
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 {return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);}} catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Bean instantiation via constructor failed", ex);}}
经过上面复杂的对比过程,终于得到了合适的构造函数、参数类型、参数值,接下来开始实例化对象。
首先获取实例化的策略,一共有三种策略定义在接口 InstantiationStrategy 中:
- 无参构造实例化;
 - 指定构造函数实例化;
 工厂方法实例化;
它有两个主要的实现类:
来到实例化方法,这里就开始区分来使用不同的实例化策略。
org.springframework.beans.factory.support.SimpleInstantiationStrategy#instantiate@Overridepublic 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;});}return BeanUtils.instantiateClass(ctor, args);}else {return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);}}
策略 SimpleInstantiationStrategy
如果 bean 没有 MethodOverrides(没有配置过 lookup-method 或 replaced-method) 那么可以继续处理。继续调用 BeanUtils.instantiateClass(ctor, args),来实例化对象。
org.springframework.beans.BeanUtils#instantiateClasspublic 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);}}catch (InstantiationException ex) {throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);}catch (IllegalAccessException ex) {throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);}catch (IllegalArgumentException ex) {throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);}catch (InvocationTargetException ex) {throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());}}
策略 CglibSubclassingInstantiationStrategy
如果 bean 有 MethodOverrides ,那么 SimpleInstantiationStrategy 就处理不了了,需要委托CglibSubclassingInstantiationStrategy 去处理。
org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy#instantiateWithMethodInjection@Overrideprotected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,@Nullable Constructor<?> ctor, Object... args) {// Must generate CGLIB subclass...return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);}
org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy.CglibSubclassCreator#instantiate
public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {Class<?> subclass = createEnhancedSubclass(this.beanDefinition);Object instance;if (ctor == null) {instance = BeanUtils.instantiateClass(subclass);}else {try {Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());instance = enhancedSubclassConstructor.newInstance(args);}catch (Exception ex) {throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),"Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);}}// SPR-10785: set callbacks directly on the instance instead of in the// enhanced class (via the Enhancer) in order to avoid memory leaks.Factory factory = (Factory) instance;factory.setCallbacks(new Callback[] {NoOp.INSTANCE,new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});return instance;}
