判断可否使用缓存中的构造器

  1. // Shortcut when re-creating the same bean...
  2. // 标记是否有缓存的构造方法
  3. boolean resolved = false;
  4. // 缓存的构造器是否有参数,如果没有表示:需要自动匹配
  5. boolean autowireNecessary = false;
  6. // 如果没有参数
  7. if (args == null) {
  8. synchronized (mbd.constructorArgumentLock) {
  9. // 已经缓存的构造方法或者工厂方法(Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,
  10. // 避免再次创建相同bean时再次解析)
  11. if (mbd.resolvedConstructorOrFactoryMethod != null) {
  12. resolved = true;
  13. autowireNecessary = mbd.constructorArgumentsResolved;
  14. }
  15. }
  16. }
  17. // 表示有缓存的构造方法,利用已经解析好的构造方法去实例化对象
  18. if (resolved) {
  19. if (autowireNecessary) {
  20. // 构造器有参数,构造函数自动注入
  21. return autowireConstructor(beanName, mbd, null, null);
  22. } else {
  23. // 默认构造函数
  24. return instantiateBean(beanName, mbd);
  25. }
  26. }

从bean后置处理器中为自动装配寻找构造方法

  1. // Candidate constructors for autowiring?
  2. // 从bean后置处理器中为自动装配寻找构造方法,比如:AutowiredAnnotationBeanPostProcessor
  3. Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
  4. if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
  5. mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
  6. return autowireConstructor(beanName, mbd, ctors, args);
  7. }

通过 determineConstructorsFromBeanPostProcessors 得到扩展的构造方法。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors

  1. @Nullable
  2. protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
  3. throws BeansException {
  4. if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
  5. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  6. if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
  7. SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
  8. Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
  9. if (ctors != null) {
  10. return ctors;
  11. }
  12. }
  13. }
  14. }
  15. return null;
  16. }

找出最合适的构造方法

  1. ctors = mbd.getPreferredConstructors();
  2. if (ctors != null) {
  3. // 构造函数自动注入
  4. return autowireConstructor(beanName, mbd, ctors, null);
  5. }

🔥 autowireConstructor

上面的推断方式最终还是会走到这个方法,利用带参数的构造函数去实例化对象,是最复杂的一种,因为不确定太多。所以这块的代码相当的长了。
首先开发者可以通过什么方式来指定使用哪个构造方法呢?
https://www.jb51.net/article/264134.htm

  1. 通过xml中的标签,这个标签表示构造方法参数,所以可以根据这个确定想要使用的构造方法的参数个数,从而确定想要使用的构造方法;
  2. 通过@Autowired注解,@Autowired注解可以写在构造方法上,所以哪个构造方法上写了@Autowired注解,表示开发者想使用哪个构造方法,当然,它和第一个方式的不同点是,通过xml的方式,我们直接指定了构造方法的参数值,而通过@Autowired注解的方式,需要Spring通过byType+byName的方式去找到符合条件的bean作为构造方法的参数值;
  3. 如果Bean为注解@Lazy修饰的或者非单例的,可以通过getBean方法设置构造方法的入参,达到指定构造方法的效果。如,applicationContext.getBean(“BeanDemo”, new CircularRefA());【同理,获取beanDefinition,使用beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(new CircularRefA());指定构造方法参数】

接下来解析这块复杂的代码。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireConstructor

  1. protected BeanWrapper autowireConstructor(String beanName
  2. , RootBeanDefinition mbd
  3. , @Nullable Constructor<?>[] ctors
  4. , @Nullable Object[] explicitArgs) {
  5. return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
  6. }

org.springframework.beans.factory.support.ConstructorResolver#autowireConstructor

  1. public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
  2. @Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
  3. BeanWrapperImpl bw = new BeanWrapperImpl();
  4. this.beanFactory.initBeanWrapper(bw);
  5. Constructor<?> constructorToUse = null;
  6. ArgumentsHolder argsHolderToUse = null;
  7. Object[] argsToUse = null;
  8. // 如果有构造函数的参数直接使用
  9. if (explicitArgs != null) {
  10. argsToUse = explicitArgs;
  11. } else {
  12. // 没有尝试从缓存中得到
  13. Object[] argsToResolve = null;
  14. synchronized (mbd.constructorArgumentLock) {
  15. constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
  16. if (constructorToUse != null && mbd.constructorArgumentsResolved) {
  17. // Found a cached constructor...
  18. argsToUse = mbd.resolvedConstructorArguments;
  19. if (argsToUse == null) {
  20. argsToResolve = mbd.preparedConstructorArguments;
  21. }
  22. }
  23. }
  24. // 从缓存中得到了参数
  25. if (argsToResolve != null) {
  26. // 解析参数类型,比如 Student(int,int),通过此方法将参数从("1","1")转换成(1,1)
  27. argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
  28. }
  29. }
  30. // 缓存中没有
  31. if (constructorToUse == null || argsToUse == null) {
  32. // Take specified constructors, if any.
  33. Constructor<?>[] candidates = chosenCtors;
  34. if (candidates == null) {
  35. // 如果参数没有给构造函数,那么尝试从定义中获取
  36. Class<?> beanClass = mbd.getBeanClass();
  37. try {
  38. candidates = (mbd.isNonPublicAccessAllowed() ? beanClass.getDeclaredConstructors() : beanClass.getConstructors());
  39. } catch (Throwable ex) {
  40. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  41. "Resolution of declared constructors on bean Class [" + beanClass.getName() +
  42. "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
  43. }
  44. }
  45. // 如果只有一个构造函数,并且没有参数。那就是默认的构造函数了。
  46. if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
  47. Constructor<?> uniqueCandidate = candidates[0];
  48. if (uniqueCandidate.getParameterCount() == 0) {
  49. synchronized (mbd.constructorArgumentLock) {
  50. mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
  51. mbd.constructorArgumentsResolved = true;
  52. mbd.resolvedConstructorArguments = EMPTY_ARGS;
  53. }
  54. bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
  55. return bw;
  56. }
  57. }
  58. // 判断是否需要自动装配
  59. boolean autowiring = (chosenCtors != null ||
  60. mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
  61. // 持有构造器的参数和值
  62. ConstructorArgumentValues resolvedValues = null;
  63. // 最少参数的个数
  64. int minNrOfArgs;
  65. if (explicitArgs != null) {
  66. minNrOfArgs = explicitArgs.length;
  67. } else {
  68. // 获取解析阶段得到的构造函数信息
  69. ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
  70. resolvedValues = new ConstructorArgumentValues();
  71. // 解析构造器的参数和值,从而得到构造器使用最少参数的数量
  72. minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
  73. }
  74. // 排序给定的构造函数,public构造函数优先参数数量降序、非public构造函数参数数量降序
  75. AutowireUtils.sortConstructors(candidates);
  76. // 最小差异值
  77. int minTypeDiffWeight = Integer.MAX_VALUE;
  78. Set<Constructor<?>> ambiguousConstructors = null;
  79. LinkedList<UnsatisfiedDependencyException> causes = null;
  80. // 遍历所有构造函数,找到最合适的
  81. for (Constructor<?> candidate : candidates) {
  82. // 当前构造函数参数的数量
  83. int parameterCount = candidate.getParameterCount();
  84. // 如果 constructorToUse argsToUse 不空,并且 参数数量够用,就不用继续找了
  85. if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
  86. // Already found greedy constructor that can be satisfied ->
  87. // do not look any further, there are only less greedy constructors left.
  88. break;
  89. }
  90. // 参数比最小参数还小,不够用,继续找
  91. if (parameterCount < minNrOfArgs) {
  92. continue;
  93. }
  94. ArgumentsHolder argsHolder;
  95. // 参数类型的数组
  96. Class<?>[] paramTypes = candidate.getParameterTypes();
  97. if (resolvedValues != null) {
  98. try {
  99. // 从注解上获取参数名称
  100. String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
  101. if (paramNames == null) {
  102. // 获取配置的参数名称
  103. ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
  104. if (pnd != null) {
  105. paramNames = pnd.getParameterNames(candidate);
  106. }
  107. }
  108. argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
  109. getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
  110. } catch (UnsatisfiedDependencyException ex) {
  111. if (logger.isTraceEnabled()) {
  112. logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
  113. }
  114. // Swallow and try next constructor.
  115. if (causes == null) {
  116. causes = new LinkedList<>();
  117. }
  118. causes.add(ex);
  119. continue;
  120. }
  121. } else {
  122. // Explicit arguments given -> arguments length must match exactly.
  123. if (parameterCount != explicitArgs.length) {
  124. continue;
  125. }
  126. argsHolder = new ArgumentsHolder(explicitArgs);
  127. }
  128. // 如果是宽松模式就走方法getTypeDifferenceWeight;否则走getAssignabilityWeight
  129. int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
  130. argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
  131. // Choose this constructor if it represents the closest match.
  132. if (typeDiffWeight < minTypeDiffWeight) {
  133. constructorToUse = candidate;
  134. argsHolderToUse = argsHolder;
  135. argsToUse = argsHolder.arguments;
  136. minTypeDiffWeight = typeDiffWeight;
  137. ambiguousConstructors = null;
  138. } else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
  139. if (ambiguousConstructors == null) {
  140. ambiguousConstructors = new LinkedHashSet<>();
  141. ambiguousConstructors.add(constructorToUse);
  142. }
  143. ambiguousConstructors.add(candidate);
  144. }
  145. }
  146. // 如果遍历了所有的构造函数,依然没有找到,就要记录异常了
  147. if (constructorToUse == null) {
  148. if (causes != null) {
  149. UnsatisfiedDependencyException ex = causes.removeLast();
  150. for (Exception cause : causes) {
  151. this.beanFactory.onSuppressedException(cause);
  152. }
  153. throw ex;
  154. }
  155. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  156. "Could not resolve matching constructor on bean class [" + mbd.getBeanClassName() + "] " +
  157. "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
  158. } else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
  159. // 存在不能直接访问的构造函数,并且不是宽松的访问 ,那么异常
  160. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  161. "Ambiguous constructor matches found on bean class [" + mbd.getBeanClassName() + "] " +
  162. "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
  163. ambiguousConstructors);
  164. }
  165. // 解析得到的参数加入缓存
  166. if (explicitArgs == null && argsHolderToUse != null) {
  167. argsHolderToUse.storeCache(mbd, constructorToUse);
  168. }
  169. }
  170. // 实例化
  171. Assert.state(argsToUse != null, "Unresolved constructor arguments");
  172. bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
  173. return bw;
  174. }

构造函数创建对象,最终都会来到这个方法,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. 实例化对象
没有问题的话,根据构造函数及参数去实例化对象。

确定构造函数的参数

  1. // 如果有构造函数的参数直接使用
  2. if (explicitArgs != null) {
  3. argsToUse = explicitArgs;
  4. } else {
  5. // 没有尝试从缓存中得到
  6. Object[] argsToResolve = null;
  7. synchronized (mbd.constructorArgumentLock) {
  8. constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
  9. if (constructorToUse != null && mbd.constructorArgumentsResolved) {
  10. // Found a cached constructor...
  11. argsToUse = mbd.resolvedConstructorArguments;
  12. if (argsToUse == null) {
  13. argsToResolve = mbd.preparedConstructorArguments;
  14. }
  15. }
  16. }
  17. // 从缓存中得到了参数
  18. if (argsToResolve != null) {
  19. // 解析参数类型,比如 Student(int,int),通过此方法将参数从("1","1")转换成(1,1)
  20. argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
  21. }
  22. }

首先判断方法是否传递了参数 explicitArgs ,这个参数是通过代码指定的,并非从配置文件而来,所以如果这个参数存在的话,那么应该使用的构造函数和参数就是确定的,不用再解析了。
如果这个参数不存在的话,就去缓存找构造函数和参数,查询到需要对缓存的数据进行解析,通过方法 resolvePreparedArguments。查询不到的话就去解析 Beandefinition。
解析其实就是把 argsToResolve 解析到 argsToUse,如下所示:
argsToResolve = mbd.preparedConstructorArguments;
image.png
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
image.png

得到所有构造函数

有了参数之后,开始确定到底使用哪个构造函数。
同样构造函数可以通过方法传递进来,如果没有的话,那么也是从 BeanDefinition 缓存中获取(可能有多个)
如果判断只有一个构造函数,并且还没有参数,别无选择,只能使用这个唯一构造函数去实例化。
大多数情况下可能有多个构造函数:
得到构造函数的参数个数 minNrOfArgs。

  1. int minNrOfArgs;
  2. if (explicitArgs != null) {
  3. minNrOfArgs = explicitArgs.length;
  4. } else {
  5. // 获取解析阶段得到的构造函数信息
  6. ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
  7. resolvedValues = new ConstructorArgumentValues();
  8. // 解析构造器的参数和值,从而得到构造器使用最少参数的数量
  9. minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
  10. }

ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
这个是我们在 BeanDefinition 解析阶段解析标签得到的数据。系统默认标签解析-解析 constructor-arg 标签
然后通过方法 resolveConstructorArguments 解析里面参数,将解析的结果放到 resolvedValues 中,同时统计了参数个数。

  1. private int resolveConstructorArguments(String beanName
  2. , RootBeanDefinition mbd
  3. , BeanWrapper bw
  4. , ConstructorArgumentValues cargs
  5. , ConstructorArgumentValues resolvedValues) {
  6. TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
  7. TypeConverter converter = (customConverter != null ? customConverter : bw);
  8. BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
  9. // 参数数量的最小值,默认是按照索引配置的参数的数量 + 按照名称配置的参数的数量
  10. /*
  11. <bean id="pig" class="cn.lichenghao.createBeanInstance.entity.Pig">
  12. <constructor-arg name="id" value="红猪"></constructor-arg>
  13. <constructor-arg index="1" value="222"></constructor-arg>
  14. <constructor-arg index="2" value="222"></constructor-arg>
  15. <constructor-arg index="3" value="222"></constructor-arg>
  16. </bean>
  17. 或者
  18. <bean id="pig" class="cn.lichenghao.createBeanInstance.entity.Pig">
  19. <constructor-arg index="0" value="222"></constructor-arg>
  20. <constructor-arg index="1" value="222"></constructor-arg>
  21. <constructor-arg name="age" value="111"></constructor-arg>
  22. <constructor-arg index="3" value="222"></constructor-arg>
  23. </bean>
  24. */
  25. int minNrOfArgs = cargs.getArgumentCount(); //4
  26. // 遍历根据位置配置的参数
  27. for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
  28. int index = entry.getKey();
  29. if (index < 0) {
  30. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid constructor argument index: " + index);
  31. }
  32. if (index + 1 > minNrOfArgs) {
  33. minNrOfArgs = index + 1;
  34. }
  35. // 参数的值没有转换的话,进行转换,记录在resolvedValues中
  36. ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
  37. if (valueHolder.isConverted()) {
  38. resolvedValues.addIndexedArgumentValue(index, valueHolder);
  39. } else {
  40. Object resolvedValue =
  41. valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
  42. ConstructorArgumentValues.ValueHolder resolvedValueHolder =
  43. new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
  44. resolvedValueHolder.setSource(valueHolder);
  45. resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
  46. }
  47. }
  48. for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
  49. // 参数的值没有转换的话,进行转换,记录在resolvedValues中
  50. if (valueHolder.isConverted()) {
  51. resolvedValues.addGenericArgumentValue(valueHolder);
  52. } else {
  53. Object resolvedValue =
  54. valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
  55. ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(
  56. resolvedValue, valueHolder.getType(), valueHolder.getName());
  57. resolvedValueHolder.setSource(valueHolder);
  58. resolvedValues.addGenericArgumentValue(resolvedValueHolder);
  59. }
  60. }
  61. return minNrOfArgs;
  62. }

给构造函数排个序。
排序规则:public构造函数优先参数数量降序、非public构造函数参数数量降序。

  1. AutowireUtils.sortConstructors(candidates);
  2. public static void sortConstructors(Constructor<?>[] constructors) {
  3. Arrays.sort(constructors, EXECUTABLE_COMPARATOR);
  4. }
  5. public static final Comparator<Executable> EXECUTABLE_COMPARATOR = (e1, e2) -> {
  6. int result = Boolean.compare(Modifier.isPublic(e2.getModifiers()), Modifier.isPublic(e1.getModifiers()));
  7. return result != 0 ? result : Integer.compare(e2.getParameterCount(), e1.getParameterCount());
  8. };

得到每个构造函数的参数信息

这一步会变量所有的构造函数,得到每个构造函数的参数相关信息。

  1. for (Constructor<?> candidate : candidates) {
  2. ........
  3. }

获取构造函数参数的数量 parameterCount,如果比 minNrOfArgs 还小,参数不够啊,继续找下一个;

  1. int parameterCount = candidate.getParameterCount();
  2. // 参数比最小参数还小,不够用,继续找
  3. if (parameterCount < minNrOfArgs) {
  4. continue;
  5. }

判断 resolvedValues :

  1. ArgumentsHolder argsHolder;
  2. // 参数类型的数组
  3. Class<?>[] paramTypes = candidate.getParameterTypes();
  4. if (resolvedValues != null) {
  5. try {
  6. // 从注解上获取参数名称
  7. String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
  8. if (paramNames == null) {
  9. // 获取配置的参数名称
  10. ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
  11. if (pnd != null) {
  12. paramNames = pnd.getParameterNames(candidate);
  13. }
  14. }
  15. argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
  16. getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
  17. } catch (UnsatisfiedDependencyException ex) {
  18. if (logger.isTraceEnabled()) {
  19. logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
  20. }
  21. // Swallow and try next constructor.
  22. if (causes == null) {
  23. causes = new LinkedList<>();
  24. }
  25. causes.add(ex);
  26. continue;
  27. }
  28. } else {
  29. // Explicit arguments given -> arguments length must match exactly.
  30. if (parameterCount != explicitArgs.length) {
  31. continue;
  32. }
  33. argsHolder = new ArgumentsHolder(explicitArgs);
  34. }

分成不同的分支:

分支 说明
resolvedValues==null 说明用户可能在 getBean 环节提供了构造函数的参数,那么判断下参数个数是否等于用户给定的 explicitArgs 参数个数,不等判断下一个构造函数;相等的话,就留下来,继续后面的对比。
resolvedValues==null && 没有提供相关 explicitArgs 说明用户没有配置构造函数的参数,也就意味着后面的逻辑都不会走。直接都不用判断了,会直接走无参构造。
resolvedValues != null 解析构造函数的参数名称。

如果 resolvedValues != null 那么需要进一步解析得到当前构造函数的参数名称信息。有如下两种方式得到。
第一种方式:

  1. 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

  1. private static class ConstructorPropertiesChecker {
  2. @Nullable
  3. public static String[] evaluate(Constructor<?> candidate, int paramCount) {
  4. ConstructorProperties cp = candidate.getAnnotation(ConstructorProperties.class);
  5. if (cp != null) {
  6. String[] names = cp.value();
  7. if (names.length != paramCount) {
  8. throw new IllegalStateException("Constructor annotated with @ConstructorProperties but not " +
  9. "corresponding to actual number of parameters (" + paramCount + "): " + candidate);
  10. }
  11. return names;
  12. } else {
  13. return null;
  14. }
  15. }
  16. }

第二种方式:
直接解析构造函数中定义的参数名称。

  1. ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
  2. if (pnd != null) {
  3. paramNames = pnd.getParameterNames(candidate);
  4. }

到此,先整理下,我们都得到了哪些信息:

  1. BeanDefinition 信息;
  2. BeanWrapperImpl bean 包装对象;
  3. resolvedValues,配置文件中配置的构造函数参数信息;
  4. 当前构造函数参数的类型 paramTypes,如: [String,String];
  5. 当前构造函数参数的名称 paramNames,如: [x,y];

将解析后的数据,利用 createArgumentArray 封装到 ArgumentsHolder ,然后继续下一步的判断。

  1. argsHolder = createArgumentArray(beanName
  2. , mbd
  3. , resolvedValues
  4. , bw
  5. , paramTypes
  6. , paramNames
  7. , getUserDeclaredConstructor(candidate)
  8. , autowiring
  9. , candidates.length == 1);

其中方法 getUserDeclaredConstructor 用于判断 candidate 构造函数是否是 cglib 代码对象的构造函数,如果是的话,返回原始对象的构造函数。

  1. protected Constructor<?> getUserDeclaredConstructor(Constructor<?> constructor) {
  2. // 获取构造函数对应的Class对象
  3. Class<?> declaringClass = constructor.getDeclaringClass();
  4. // 如果是 cglib 代理类,返回原始 Class
  5. Class<?> userClass = ClassUtils.getUserClass(declaringClass);
  6. // 不等说明constructor是cglib代理类的构造函数
  7. if (userClass != declaringClass) {
  8. try {
  9. // 获取原始Class中的构造函数
  10. return userClass.getDeclaredConstructor(constructor.getParameterTypes());
  11. } catch (NoSuchMethodException ex) {
  12. // No equivalent constructor on user class (superclass)...
  13. // Let's proceed with the given constructor as we usually would.
  14. }
  15. }
  16. return constructor;
  17. }

那么继续进入方法 createArgumentArray .

对比构造函数是否满足

对比有两种模式,一种 lenientConstructorResolution = true 宽松模式, 另外一种是 lenientConstructorResolution = false,分别通过 getTypeDifferenceWeight 和 getAssignabilityWeight 计算出对应的差异值。

getTypeDifferenceWeight

比较参数值的类型。

  1. public int getTypeDifferenceWeight(Class<?>[] paramTypes) {
  2. // If valid arguments found, determine type difference weight.
  3. // Try type difference weight on both the converted arguments and
  4. // the raw arguments. If the raw weight is better, use it.
  5. // Decrease raw weight by 1024 to prefer it over equal converted weight.
  6. int typeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.arguments);
  7. int rawTypeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.rawArguments) - 1024;
  8. return Math.min(rawTypeDiffWeight, typeDiffWeight);
  9. }

重载方法
org.springframework.util.MethodInvoker#getTypeDifferenceWeight

  1. public static int getTypeDifferenceWeight(Class<?>[] paramTypes, Object[] args) {
  2. int result = 0;
  3. for (int i = 0; i < paramTypes.length; i++) {
  4. if (!ClassUtils.isAssignableValue(paramTypes[i], args[i])) {
  5. // 如果args[i]==null 并且 paramTypes[i] 是基本类型
  6. // 如果args[i]!=null 并且 args[i]不是paramTypes[i]同类,也不是子类
  7. // 说明不是空,就是类型根本一点边都不着
  8. return Integer.MAX_VALUE;
  9. }
  10. if (args[i] != null) {
  11. // 参数类型
  12. Class<?> paramType = paramTypes[i];
  13. // 参数值的父类
  14. Class<?> superClass = args[i].getClass().getSuperclass();
  15. while (superClass != null) {
  16. if (paramType.equals(superClass)) {
  17. result = result + 2;
  18. superClass = null;
  19. } else if (ClassUtils.isAssignable(paramType, superClass)) {
  20. result = result + 2;
  21. superClass = superClass.getSuperclass();
  22. } else {
  23. superClass = null;
  24. }
  25. }
  26. if (paramType.isInterface()) {
  27. result = result + 1;
  28. }
  29. }
  30. }
  31. return result;
  32. }

遍历参数类型,开始分析每个参数值。

第一种情况:

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 ,开始循环判断当前参数值的每一个父类:

  1. 如果 paramType==superClass的话,那么匹配度+2,结束循环;
  2. 如果 ClassUtils.isAssignable(paramType, superClass) 匹配度+2,继续比较该父类的父类,相当于一个父类就+2;
  3. 如果以上都不满足,结束循环。

如果参数的类型为接口类型,那么匹配度+1。
依次比较每一个参数类型和参数值类型,最终得到 typeDiffWeight。


上面的文字描述感觉晕晕的,可以用一段代码来验证测试下。
假如我们有如下类:A extend B implements D ;B etend C

  1. public class A extends B implements D {
  2. public static void main(String[] args) {
  3. Object[] myArgs = new Object[]{new A()};
  4. // 参数类型为A,完全匹配 0
  5. System.out.println(MethodInvoker.getTypeDifferenceWeight(new Class[]{A.class}, myArgs));
  6. // 参数类型为B,父类匹配 2
  7. System.out.println(MethodInvoker.getTypeDifferenceWeight(new Class[]{B.class}, myArgs));
  8. // 参数类型为C,父父匹配 4
  9. System.out.println(MethodInvoker.getTypeDifferenceWeight(new Class[]{C.class}, myArgs));
  10. // 参数类型为D,接口匹配 1
  11. System.out.println(MethodInvoker.getTypeDifferenceWeight(new Class[]{D.class}, myArgs));
  12. }
  13. }
  14. public class B extends C{
  15. }
  16. public class C {
  17. }
  18. public interface D {
  19. }

好,回到方法。分别用 arguments 和 rawArguments 做了比对。
这俩参数的区别:
arguments:参数类型是经过转换的,比如:xx(String,String) ——> xx(12(Integer),”122”(String))
rawArguments:原始的可能是 xx(String,String)

  1. public int getTypeDifferenceWeight(Class<?>[] paramTypes) {
  2. // If valid arguments found, determine type difference weight.
  3. // Try type difference weight on both the converted arguments and
  4. // the raw arguments. If the raw weight is better, use it.
  5. // Decrease raw weight by 1024 to prefer it over equal converted weight.
  6. int typeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.arguments);
  7. int rawTypeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.rawArguments) - 1024;
  8. return Math.min(rawTypeDiffWeight, typeDiffWeight);
  9. }

然后取这俩的最小值。

getAssignabilityWeight

  1. public int getAssignabilityWeight(Class<?>[] paramTypes) {
  2. for (int i = 0; i < paramTypes.length; i++) {
  3. if (!ClassUtils.isAssignableValue(paramTypes[i], this.arguments[i])) {
  4. return Integer.MAX_VALUE;
  5. }
  6. }
  7. for (int i = 0; i < paramTypes.length; i++) {
  8. if (!ClassUtils.isAssignableValue(paramTypes[i], this.rawArguments[i])) {
  9. return Integer.MAX_VALUE - 512;
  10. }
  11. }
  12. return Integer.MAX_VALUE - 1024;
  13. }

这个方法就比上个看着简单多了,主要是利用了 ClassUtils.isAssignableValue 方法。参考:ClassUtil

对比权重结果

经过上面的比对得到的 typeDiffWeight 权重和 minTypeDiffWeight 对比。
比 minTypeDiffWeight 小的话那么就是符合的构造函数。记录对应的构造函数及相关参数。否则记录信息到 ambiguousConstructors 中。继续下一个构造函数的对比。
最终对比完毕后,并没有找到合适,那么就要记录相关信息。抛出异常 BeanCreationException 。

使用构造函数实例化

  1. private Object instantiate(
  2. String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) {
  3. try {
  4. InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
  5. if (System.getSecurityManager() != null) {
  6. return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
  7. strategy.instantiate(mbd, beanName
  8. , this.beanFactory, constructorToUse, argsToUse),
  9. this.beanFactory.getAccessControlContext());
  10. } else {
  11. return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
  12. }
  13. } catch (Throwable ex) {
  14. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  15. "Bean instantiation via constructor failed", ex);
  16. }
  17. }

经过上面复杂的对比过程,终于得到了合适的构造函数、参数类型、参数值,接下来开始实例化对象。
首先获取实例化的策略,一共有三种策略定义在接口 InstantiationStrategy 中:

  1. 无参构造实例化;
  2. 指定构造函数实例化;
  3. 工厂方法实例化; 4. 推断构造函数创建对象 - 图3它有两个主要的实现类: 4. 推断构造函数创建对象 - 图4来到实例化方法,这里就开始区分来使用不同的实例化策略。
    org.springframework.beans.factory.support.SimpleInstantiationStrategy#instantiate

    1. @Override
    2. public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
    3. final Constructor<?> ctor, Object... args) {
    4. if (!bd.hasMethodOverrides()) {
    5. if (System.getSecurityManager() != null) {
    6. // use own privileged to change accessibility (when security is on)
    7. AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    8. ReflectionUtils.makeAccessible(ctor);
    9. return null;
    10. });
    11. }
    12. return BeanUtils.instantiateClass(ctor, args);
    13. }
    14. else {
    15. return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
    16. }
    17. }

    策略 SimpleInstantiationStrategy

    如果 bean 没有 MethodOverrides(没有配置过 lookup-method 或 replaced-method) 那么可以继续处理。继续调用 BeanUtils.instantiateClass(ctor, args),来实例化对象。
    org.springframework.beans.BeanUtils#instantiateClass

    1. public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
    2. Assert.notNull(ctor, "Constructor must not be null");
    3. try {
    4. ReflectionUtils.makeAccessible(ctor);
    5. if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
    6. return KotlinDelegate.instantiateClass(ctor, args);
    7. }
    8. else {
    9. Class<?>[] parameterTypes = ctor.getParameterTypes();
    10. Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
    11. Object[] argsWithDefaultValues = new Object[args.length];
    12. for (int i = 0 ; i < args.length; i++) {
    13. if (args[i] == null) {
    14. Class<?> parameterType = parameterTypes[i];
    15. argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
    16. }
    17. else {
    18. argsWithDefaultValues[i] = args[i];
    19. }
    20. }
    21. return ctor.newInstance(argsWithDefaultValues);
    22. }
    23. }
    24. catch (InstantiationException ex) {
    25. throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
    26. }
    27. catch (IllegalAccessException ex) {
    28. throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
    29. }
    30. catch (IllegalArgumentException ex) {
    31. throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
    32. }
    33. catch (InvocationTargetException ex) {
    34. throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
    35. }
    36. }

    策略 CglibSubclassingInstantiationStrategy

    如果 bean 有 MethodOverrides ,那么 SimpleInstantiationStrategy 就处理不了了,需要委托CglibSubclassingInstantiationStrategy 去处理。
    org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy#instantiateWithMethodInjection

    1. @Override
    2. protected Object instantiateWithMethodInjection(RootBeanDefinition bd
    3. , @Nullable String beanName, BeanFactory owner,
    4. @Nullable Constructor<?> ctor, Object... args) {
    5. // Must generate CGLIB subclass...
    6. return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
    7. }

    org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy.CglibSubclassCreator#instantiate

    1. public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {
    2. Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
    3. Object instance;
    4. if (ctor == null) {
    5. instance = BeanUtils.instantiateClass(subclass);
    6. }
    7. else {
    8. try {
    9. Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
    10. instance = enhancedSubclassConstructor.newInstance(args);
    11. }
    12. catch (Exception ex) {
    13. throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
    14. "Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
    15. }
    16. }
    17. // SPR-10785: set callbacks directly on the instance instead of in the
    18. // enhanced class (via the Enhancer) in order to avoid memory leaks.
    19. Factory factory = (Factory) instance;
    20. factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
    21. new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
    22. new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
    23. return instance;
    24. }