1.写在前面
上篇博客主要讲了一些Spring的推断构造函数的过程,同时也讲了一下多种的情况,具体可以参考我的博客:Spring源码系列(十三)Spring创建Bean的过程(三),今天要讲的就是普通方式实例化Bean的过程,废话不多说,直接上代码。
2.Spring中自动装配模式实例化Bean
上篇博客我们主要讲了下Spring中的构造函数的推断,同时也得出了一些结论,主要讲的还是createBeanInstance()
方法,具体的代码如下:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
// 获取Bean的Class,这儿获取的A.Class,因为笔者条件断点的是a
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());
}
//获取供给型的接口,直接创建Bean
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//通过工厂方法推断构造函数,同时创建对应的对象
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
//这个参数一般的情况都是为空
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 这个参数只有在@Bean注解的方法的时候创建RootBeanDefinition的才会这个参数赋值,而@Bean注解的方法在上面
// instantiateUsingFactoryMethod(beanName, mbd, args);已经创建完成返回了。
// 所以这个判断只有在创建RootBeanDefinition的时候,同时它的工厂方法名为空,然后这个解析的工厂方法名不为空的时候,才会进入这个判断
// 已经缓存的构造函数
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
// constructorArgumentsResolved默认为false
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//只有上面判断执行,这个判断才会执行,一般情况下不会执行
if (resolved) {
if (autowireNecessary) {
//通过自动装配的构造函数方式实例化Bean
return autowireConstructor(beanName, mbd, null, null);
}
else {
//实例化Bean
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
// 推断构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}
今天我们要讲的代码如下:
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
上面if判断分别对应了四个条件,一般情况下最后条件都是不满足的。下面我们就分三个小节来讲这个判断吧。
2.1ctors != null
ctors != null这个条件成立?我们可以看下上篇博客的总结,具体的总结如下:
- 默认的无参的构造函数(没有加@Autowired注解),返回的是null。
- 有且只有一个构造函数(加了@Autowired注解),不管注解中的required的值是true还是false,都会返回这个构造函数。
- 提供一个带参数的构造函数,同时这个构造函数上面没有添加@Autowired注解,这个时候返回的就是这个唯一的构造函数。
- 多个构造函数,没有提供@Autowired注解,这个时候返回的就是null
- 多个构造函数(只有一个构造函数添加了@Autowired注解),如果这个@Autowired注解中required的值等于true,就会返回这个加了@Autowired注解的构造函数。如果这个@Autowired注解中required的值等于false,并且这个@Autowired的注解没有加到无参的构造函数上,这个时候就会返回加了@Autowired注解的函数和无参的构造函数。
- 多个构造函数,都加了@Autowired注解,并且这些注解中的required的值是true的话,就直接会抛出异常,如果其中只有一个@Autowired(required=true)的话,也是会直接抛出异常。也就是说,除了所有的@Autowired(required=false)的情况下会不报错,其他组合多个@Autowired都会报错。
- 多个构造函数,每个构造函数都加了@Autowired(required=false)的注解,这个时候返回的就是所有加了这个@Autowired(required=false)的构造函数。
2.11提供一个构造函数加了@Autowired注解
上面的第二个条件,返回的不是空,所以我们情景再现一下,先是无参的构造函数。具体的代码如下:
package com.ys.beanLife.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class A{
@Autowired()
public A() {
}
}
这个找出来的就是加了@Autowired
注解的构造函数,然后调用就是autowireConstructor(beanName, mbd, ctors, args)
方法,具体的代码如下,由于这个代码比较长,我们分开讲。
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
//创建Bean的包装对象
BeanWrapperImpl bw = new BeanWrapperImpl();
//初始化Bean的包装对象
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) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
}
}
//这个判断是成立的
if (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
// 将找到的构造函数赋值给candidates
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);
}
}
//判断candidates长度是不是等于1,第二条件默认成立,这儿也没有传入对应的构造函数的值,所有这个if成立
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;
}
}
// Need to resolve the constructor.
// 省略一部分代码
}
讲完了第一种是无参的情况下,笔者再来讲下不是无参的情况,具体的代码如下:
package com.ys.beanLife.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class A{
@Autowired()
public A(B b) {
}
}
于是前面判断都不会成立,于是会走我们剩下的代码,具体代码如下:
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;
//省略一部分代码
// Need to resolve the constructor.
// 这个值在这种情况下就是true
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
// 解析的构造参数的值
ConstructorArgumentValues resolvedValues = null;
//最小参数的个数
int minNrOfArgs;
//这个值默认为空的
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
//获取设置好的构造参数的值,这儿取出来的两个属性的长度应该都是0,这个方法的规则前面的博客有讲
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
//排序,排序的规则前面的博客笔者有讲
// pulic第一优先级,参数个数第二优先级
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
//有歧义的构造函数
Set<Constructor<?>> ambiguousConstructors = null;
//存放错误的集合
LinkedList<UnsatisfiedDependencyException> causes = null;
//遍历所有的传进来的构造函数
for (Constructor<?> candidate : candidates) {
//获取对应的构造函数的参数的个数
int parameterCount = candidate.getParameterCount();
//已经找到了要使用的构造函数和构造函数的参数,同时这个待使用的构造函数参数个数大于这个构造函数的参数的个数
//满足条件的话,直接返回,由于这个时候是第一次循环所以这个不满足
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
//如果这次的遍历的参数的个数小于最小使用的参数的个数,直接跳过这个
if (parameterCount < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
//获取所有构造函数的参数的类型
Class<?>[] paramTypes = candidate.getParameterTypes();
//这个值默认情况下不等于null
if (resolvedValues != null) {
try {
//用于检查Java 6的{@link ConstructorProperties}的注解。
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
//获取对应的参数的名称
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
//这个方法在前面讲过,但是这儿的情况不一样,因为autowiring的值是等于true
//getUserDeclaredConstructor(candidate)方法下面讲
//createArgumentArray方法还剩一点下面讲
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);
}
//计算权重,前面的博客笔者有介绍
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
// 这儿计算出来的肯定满足,计算的结果是-1024,然后进行对应的赋值
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
//如果已经找的了待使用的构造函数的话,并且计算出来的权重等于最小的权重,这儿只遍历一次,所有这个判断是不会进的
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
//这儿表示没有找到待使用的构造函数
if (constructorToUse == null) {
//异常不等于空,直接组装异常,然后抛出
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
//有歧义的构造函数不等于空的时候,同时是非宽松的模式的情况下,也是抛出异常
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
//传入参数等于空,同时argsHolderToUse不等于空的情况下,将这些东西缓存起来
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;
}
上面的第一个问题,就是getUserDeclaredConstructor(candidate)
是干嘛的?我们打开对应的代码,具体的代码如下:
protected Constructor<?> getUserDeclaredConstructor(Constructor<?> constructor) {
//获取定义的class类
Class<?> declaringClass = constructor.getDeclaringClass();
//如果是cglib的类,就获取对应的父类,如果不是,就获取对应的本身
Class<?> userClass = ClassUtils.getUserClass(declaringClass);
//如果不相等,证明是代理的类,直接找到对应的父类的方法。
if (userClass != declaringClass) {
try {
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()
方法还有一点点没有讲,我们继续讲,先上代码,具体的代码如下:
private ArgumentsHolder createArgumentArray(
String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,
BeanWrapper bw, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable,
boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException {
//用户自定义的类型转换器,默认是空的,因为用户没有定义
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
//如果是空的就使用默认的的类型装换器
TypeConverter converter = (customConverter != null ? customConverter : bw);
//创建参数的处理器对象
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
//创建对应集合,其中存的是构造函数的参数的封装
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
//遍历所有的参数类型
for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
//取出类型
Class<?> paramType = paramTypes[paramIndex];
//取出参数名
String paramName = (paramNames != null ? paramNames[paramIndex] : "");
// Try to find matching constructor argument value, either indexed or generic.
// 尝试找到匹配的构造函数参数值,无论是索引的还是通用的
ConstructorArgumentValues.ValueHolder valueHolder = null;
//这个值肯定不等于空,如果提供对应的构造函数的参数值,这儿其中属性值就不等于空,如果没有提供的话,获取的属性值就为空
if (resolvedValues != null) {
//获取对应的参数的值
valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
// If we couldn't find a direct match and are not supposed to autowire,
// let's try the next generic, untyped argument value as fallback:
// it could match after type conversion (for example, String -> int).
//上面取出来的值是空的,
//autowiring=true
//paramTypes.length!=resolvedValues.getArgumentCount()
//这个判断是不成立的,这个方法笔者在前面的博客有细讲
if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
}
}
//这个值只有在上面解析过后才有值,这儿也是为空
if (valueHolder != null) {
// We found a potential match - let's give it a try.
// Do not consider the same value definition multiple times!
usedValueHolders.add(valueHolder);
Object originalValue = valueHolder.getValue();
Object convertedValue;
if (valueHolder.isConverted()) {
convertedValue = valueHolder.getConvertedValue();
args.preparedArguments[paramIndex] = convertedValue;
}
else {
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
try {
convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
}
catch (TypeMismatchException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Could not convert argument value of type [" +
ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
}
Object sourceHolder = valueHolder.getSource();
if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) {
Object sourceValue = ((ConstructorArgumentValues.ValueHolder) sourceHolder).getValue();
args.resolveNecessary = true;
args.preparedArguments[paramIndex] = sourceValue;
}
}
args.arguments[paramIndex] = convertedValue;
args.rawArguments[paramIndex] = originalValue;
}
//进入这个判断,表示找不到明确的匹配项:我们应该自动装配,或者必须为给定结构创建参数数组失败
else {
//方法参数对象
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
// No explicit match found: we're either supposed to autowire or
// have to fail creating an argument array for the given constructor.
// 这儿这个值等于true,所以这个判断是不成立的
if (!autowiring) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Ambiguous argument values for parameter of type [" + paramType.getName() +
"] - did you specify the correct bean references as arguments?");
}
try {
//用于解析应该自动装配的指定参数的模板方法。主要看这个参数在不在Spring的容器中
Object autowiredArgument = resolveAutowiredArgument(
methodParam, beanName, autowiredBeanNames, converter, fallback);
//讲这些获取的值包装到ArgumentsHolder
args.rawArguments[paramIndex] = autowiredArgument;
args.arguments[paramIndex] = autowiredArgument;
args.preparedArguments[paramIndex] = autowiredArgumentMarker;
args.resolveNecessary = true;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
}
}
}
for (String autowiredBeanName : autowiredBeanNames) {
//在给定的bean被销毁之前,为给定的bean注册一个要被销毁的依赖bean。怕内存泄漏
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName +
"' via " + (executable instanceof Constructor ? "constructor" : "factory method") +
" to bean named '" + autowiredBeanName + "'");
}
}
return args;
}
上面的代码就是经过一系列的解析,最终将对应的参数封装ArgumentsHolder
对象,最后返回。然后就是计算权重,前面博客笔者讲过了,笔者这儿不赘述了,直接上结论,具体的结论如下:
这个计算权重的方法简单的来说最小值是0,也就是如果无参的话直接是0,还有就是如果构造函数所需的参数类型(传入进来的参数类型)和解析找到参数的类型是一样的也是0,再然后就是如果传入进来的参数类型是接口加1,然后会递归找到的参数类型的所有父类,直到找到对应的父类是等于当前传入进来的类,每次加上2,最后就是如果有一个参数的类型不满足的话,就直接返回int的最大值。所以这儿的类型越匹配,这儿返回的值就越小。
所以到此这第一种的情况就讲完了。我们继续看剩下的几种。
2.12多个构造函数(只有一个构造函数添加了@Autowired注解)
这儿有一个特殊的情况,就是这个@Autowired注解中required的值等于false,并且这个@Autowired的注解没有加到无参的构造函数上,这个时候就会返回加了@Autowired注解的函数和无参的构造函数。具体的测试的代码如下:
package com.ys.beanLife.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class A{
public A() {
}
@Autowired(required = false)
public A(B b) {
}
}
还是看原来的那段代码,具体的代码如下:
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;
//省略一部分代码
// Need to resolve the constructor.
// 这个值在这种情况下就是true
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
// 解析的构造参数的值
ConstructorArgumentValues resolvedValues = null;
//最小参数的个数
int minNrOfArgs;
//这个值默认为空的
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
//获取设置好的构造参数的值,这儿取出来的两个属性的长度应该都是0,这个方法的规则前面的博客有讲
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
//排序,排序的规则前面的博客笔者有讲
// pulic第一优先级,参数个数第二优先级
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
//有歧义的构造函数
Set<Constructor<?>> ambiguousConstructors = null;
//存放错误的集合
LinkedList<UnsatisfiedDependencyException> causes = null;
//遍历所有的传进来的构造函数
for (Constructor<?> candidate : candidates) {
//获取对应的构造函数的参数的个数
int parameterCount = candidate.getParameterCount();
//已经找到了要使用的构造函数和构造函数的参数,同时这个待使用的构造函数参数个数大于这个构造函数的参数的个数
//满足条件的话,直接返回,由于这个时候是第一次循环所以这个不满足
//第二次进入循环的时候,是无参的构造函数,这个条件就满足了,所有直接break,结束当前的循环
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();
//这个值默认情况下不等于null
if (resolvedValues != null) {
try {
//用于检查Java 6的{@link ConstructorProperties}的注解。
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
//获取对应的参数的名称
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
//这个方法在前面讲过,但是这儿的情况不一样,因为autowiring的值是等于true
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);
}
//计算权重,前面的博客笔者有介绍
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
// 这儿计算出来的肯定满足,计算的结果是-1024,然后进行对应的赋值
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
//如果已经找的了待使用的构造函数的话,并且计算出来的权重等于最小的权重,这儿只遍历一次,所有这个判断是不会进的
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
//这儿表示没有找到待使用的构造函数
if (constructorToUse == null) {
//异常不等于空,直接组装异常,然后抛出
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
//有歧义的构造函数不等于空的时候,同时是非宽松的模式的情况下,也是抛出异常
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
//传入参数等于空,同时argsHolderToUse不等于空的情况下,将这些东西缓存起来
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;
}
这个情况和前面的情况是差不多,唯一的区别就是在进入第二次循环的时候,这个时候是无参的构造函数,这个时候,如下的调用满足,直接结束当前的循环
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;
}
简单的来说,如果找到一个满足条件的构造函数,如果遍历后面的构造函数的参数个数是小于当前满足条件的构造函数的参数个数,那么就直接结束当前的循环。后面不继续执行,是因为这些构造函数已经排好序了,第一优先级是public,第二优先级是参数的个数。所以这种情况也讲完了,下面继续最后一种情况。
2.13多个构造函数,每个构造函数都加了@Autowired(required=false)的注解
最后一种情况,具体的测试案例如下:
package com.ys.beanLife.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class A{
@Autowired(required = false)
public A(C c) {
}
@Autowired(required = false)
public A(B b) {
}
}
还是看原来的代码
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;
//省略一部分代码
// Need to resolve the constructor.
// 这个值在这种情况下就是true
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
// 解析的构造参数的值
ConstructorArgumentValues resolvedValues = null;
//最小参数的个数
int minNrOfArgs;
//这个值默认为空的
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
//获取设置好的构造参数的值,这儿取出来的两个属性的长度应该都是0,这个方法的规则前面的博客有讲
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
//排序,排序的规则前面的博客笔者有讲
// pulic第一优先级,参数个数第二优先级
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
//有歧义的构造函数
Set<Constructor<?>> ambiguousConstructors = null;
//存放错误的集合
LinkedList<UnsatisfiedDependencyException> causes = null;
//遍历所有的传进来的构造函数
for (Constructor<?> candidate : candidates) {
//获取对应的构造函数的参数的个数
int parameterCount = candidate.getParameterCount();
//已经找到了要使用的构造函数和构造函数的参数,同时这个待使用的构造函数参数个数大于这个构造函数的参数的个数
//满足条件的话,直接返回,由于这个时候是第一次循环所以这个不满足
//第二次进入循环的时候,不满足直接不执行
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
//如果这次的遍历的参数的个数小于最小使用的参数的个数,直接跳过这个
if (parameterCount < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
//获取所有构造函数的参数的类型
Class<?>[] paramTypes = candidate.getParameterTypes();
//这个值默认情况下不等于null
if (resolvedValues != null) {
try {
//用于检查Java 6的{@link ConstructorProperties}的注解。
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
//获取对应的参数的名称
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
//这个方法在前面讲过,但是这儿的情况不一样,因为autowiring的值是等于true
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);
}
//计算权重,前面的博客笔者有介绍,这儿两次计算的结果是一样的
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
// 这儿计算出来的肯定满足,计算的结果是-1024,然后进行对应的赋值
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
//如果已经找的了待使用的构造函数的话,并且计算出来的权重等于最小的权重,这儿只遍历一次,由于第二次计算的结果和前面的一样的所以会存到有歧义的构造函数中去
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
//这儿表示没有找到待使用的构造函数
if (constructorToUse == null) {
//异常不等于空,直接组装异常,然后抛出
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
//有歧义的构造函数不等于空的时候,同时是非宽松的模式的情况下,也是抛出异常
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
//传入参数等于空,同时argsHolderToUse不等于空的情况下,将这些东西缓存起来
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;
}
上面遍历两次,计算出来的构造函数的权重都是一样,所以第二次遍历的时候,会将这个构造函数存入到有歧义的构造函数中去,但是这儿不会报错,因为Spring默认采用的是宽松的模式,如果这儿不采用宽松的模式的话,就会直接报错,我们可以试一下,创建如下的类,让Spring进行管理,具体的代码如下,原理就是通过Spring的BeanFactory的后置处理器,来修改这个模式。
package com.ys.beanLife;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Component;
@Component
public class ABeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition a = (GenericBeanDefinition) beanFactory.getBeanDefinition("a");
a.setLenientConstructorResolution(false);
}
}
运行结果如下:
至此我们第一种情况就讲完了。我们继续看原来的if的判断的其他的情况。
2.2mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR
这个时候就需要考虑,第一个条件不满足的条件下,这个条件满足的情况,我们看ctors != null这个条件不成立的时候,只有两种情况,具体的如下:
- 默认的无参的构造函数(没有加@Autowired注解),返回的是null。
- 多个构造函数,没有提供@Autowired注解,这个时候返回的就是null
2.21默认的无参的构造函数(没有加@Autowired注解)
我们先来测试第一种的情况,默认的无参的构造函数(没有加@Autowired注解),具体的测试代码如下:
package com.ys.beanLife.bean;
import org.springframework.stereotype.Component;
@Component
public class A{
}
package com.ys.beanLife;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Component;
@Component
public class ABeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition a = (GenericBeanDefinition) beanFactory.getBeanDefinition("a");
a.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
}
}
还是看原来的代码,具体的代码如下:
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
//创建Bean的包装对象
BeanWrapperImpl bw = new BeanWrapperImpl();
//初始化Bean的包装对象
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) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
}
}
//这个判断是成立的
if (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
// 将找到的构造函数赋值给candidates
Constructor<?>[] candidates = chosenCtors;
// 这儿等于null,因为笔者测试是第二种的情况
if (candidates == null) {
//先获取对应BeanClass
Class<?> beanClass = mbd.getBeanClass();
try {
//判断是否允许访问非公共的方法,默认是true
//获取所有的构造函数,这儿取出来就是一个无参的构造函数
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;
}
}
// Need to resolve the constructor.
// 省略一部分代码
}
第一种情况比较简单,就是获取所有的构造函数,由于我们这儿只有一个构造函数,同时还是无参,所以直接成立,和前面的某种情况很相似。
2.22多个构造函数,没有提供@Autowired注解
我们再来看第二种情况,就是提供了多个构造函数,每个构造函数都没加@Autowired
注解,具体的测试代码如下:
package com.ys.beanLife.bean;
import org.springframework.stereotype.Component;
@Component
public class A{
public A(B b) {
}
public A(C c, B b) {
}
}
package com.ys.beanLife;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Component;
@Component
public class ABeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition a = (GenericBeanDefinition) beanFactory.getBeanDefinition("a");
a.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
}
}
还是看原来的代码,具体的代码如下:
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 (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
// 将找到的构造函数赋值给candidates
Constructor<?>[] candidates = chosenCtors;
// 这儿等于null,因为笔者测试是第二种的情况
if (candidates == null) {
//先获取对应BeanClass
Class<?> beanClass = mbd.getBeanClass();
try {
//判断是否允许访问非公共的方法,默认是true
//获取所有的构造函数,这儿取出来就是两个构造函数
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);
}
}
// Need to resolve the constructor.
// 这个值在这种情况下就是true
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
// 解析的构造参数的值
ConstructorArgumentValues resolvedValues = null;
//最小参数的个数
int minNrOfArgs;
//这个值默认为空的
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
//获取设置好的构造参数的值,这儿取出来的两个属性的长度应该都是0,这个方法的规则前面的博客有讲
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
//排序,排序的规则前面的博客笔者有讲
// pulic第一优先级,参数个数第二优先级
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
//有歧义的构造函数
Set<Constructor<?>> ambiguousConstructors = null;
//存放错误的集合
LinkedList<UnsatisfiedDependencyException> causes = null;
//遍历所有的传进来的构造函数
for (Constructor<?> candidate : candidates) {
//获取对应的构造函数的参数的个数
int parameterCount = candidate.getParameterCount();
//已经找到了要使用的构造函数和构造函数的参数,同时这个待使用的构造函数参数个数大于这个构造函数的参数的个数
//满足条件的话,直接返回,由于这个时候是第一次循环所以这个不满足
//第二次进入循环的时候,是一个参数个数的构造函数,这个条件就满足了,所有直接break,结束当前的循环
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();
//这个值默认情况下不等于null
if (resolvedValues != null) {
try {
//用于检查Java 6的{@link ConstructorProperties}的注解。
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
//获取对应的参数的名称
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
//这个方法在前面讲过,但是这儿的情况不一样,因为autowiring的值是等于true
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);
}
//计算权重,前面的博客笔者有介绍
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
// 这儿计算出来的肯定满足,计算的结果是-1024,然后进行对应的赋值
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
//如果已经找的了待使用的构造函数的话,并且计算出来的权重等于最小的权重,这儿只遍历一次,所有这个判断是不会进的
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
//这儿表示没有找到待使用的构造函数
if (constructorToUse == null) {
//异常不等于空,直接组装异常,然后抛出
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
//有歧义的构造函数不等于空的时候,同时是非宽松的模式的情况下,也是抛出异常
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
//传入参数等于空,同时argsHolderToUse不等于空的情况下,将这些东西缓存起来
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;
}
这种情况,和前面的情况也是差不多,所以这儿笔者也不做过多的赘述,直接看注释就行了。还有最后一种情况就是参数的个数不等于空。
3.2mbd.hasConstructorArgumentValues()
这种情况就是在前面的两个条件都不成立的情况,这儿成立,也就是在上面的两种情况(默认的无参的构造函数没有加@Autowired注解、多个构造函数,没有提供@Autowired注解)的基础上,同时自动装配的模型也不是AUTOWIRE_CONSTRUCTOR
,而这里里面有两种情况就是传入的参数匹配,还有就是不匹配。
3.11默认的无参的构造函数(没有加@Autowired注解)
因为无参的构造函数,只要传入的参数,就是不满足的,所以存在满足的情况,具体的测试代码如下:
package com.ys.beanLife.bean;
import org.springframework.stereotype.Component;
@Component
public class A{
}
package com.ys.beanLife;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Component;
@Component
public class ABeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition a = (GenericBeanDefinition) beanFactory.getBeanDefinition("a");
ConstructorArgumentValues values = new ConstructorArgumentValues();
ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder("1");
values.addGenericArgumentValue(valueHolder);
a.setConstructorArgumentValues(values);
}
}
还是看原来的代码,具体的如下:
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 (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
// 将找到的构造函数赋值给candidates
Constructor<?>[] candidates = chosenCtors;
// 这儿等于null,因为笔者测试是第三种的情况
if (candidates == null) {
//先获取对应BeanClass
Class<?> beanClass = mbd.getBeanClass();
try {
//判断是否允许访问非公共的方法,默认是true
//获取所有的构造函数,这儿取出来就是一个默认的无参构造函数
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);
}
}
// Need to resolve the constructor.
// 这个值在这种情况下就是false,因为这两个条件都不成立
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
// 解析的构造参数的值
ConstructorArgumentValues resolvedValues = null;
//最小参数的个数
int minNrOfArgs;
//这个值默认为空的
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
//获取设置好的构造参数的值,这儿取出来的两个属性的长度应该都是1,这个方法的规则前面的博客有讲
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
//这个最小参数的值也是1,同时解析这个构造参数
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
//排序,排序的规则前面的博客笔者有讲
// pulic第一优先级,参数个数第二优先级
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
//有歧义的构造函数
Set<Constructor<?>> ambiguousConstructors = null;
//存放错误的集合
LinkedList<UnsatisfiedDependencyException> causes = null;
//遍历所有的传进来的构造函数
for (Constructor<?> candidate : candidates) {
//获取对应的构造函数的参数的个数
int parameterCount = candidate.getParameterCount();
//已经找到了要使用的构造函数和构造函数的参数,同时这个待使用的构造函数参数个数大于这个构造函数的参数的个数
//这个判断不成立
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
//如果这次的遍历的参数的个数小于最小使用的参数的个数,这个是成立,因为无参的构造函数的参数个数是0,所以这个循环到此就结束了
if (parameterCount < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
//获取所有构造函数的参数的类型
Class<?>[] paramTypes = candidate.getParameterTypes();
//这个值默认情况下不等于null
if (resolvedValues != null) {
try {
//用于检查Java 6的{@link ConstructorProperties}的注解。
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);
}
//计算权重,前面的博客笔者有介绍
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
// 这儿计算出来的肯定满足,计算的结果是-1024,然后进行对应的赋值
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
//如果已经找的了待使用的构造函数的话,并且计算出来的权重等于最小的权重,这儿只遍历一次,所有这个判断是不会进的
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
//这儿表示没有找到待使用的构造函数,没有找到对应的构造函数
if (constructorToUse == null) {
//异常不等于空,直接组装异常,然后抛出
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
//直接抛出异常
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
//有歧义的构造函数不等于空的时候,同时是非宽松的模式的情况下,也是抛出异常
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
//传入参数等于空,同时argsHolderToUse不等于空的情况下,将这些东西缓存起来
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;
}
这个情况就直接报错,因为你提供了对应的构造函数,而没有找到匹配的构造函数,所以这儿直接报错。
3.12多个构造函数,没有提供@Autowired注解
这个时候,具体的情况如下几种,要不都不满足,要不只有一个满足,要不全部满足,笔者都来测试一下,看看具体的是什么情况。
第一种全部不满足,具体的测试案例如下:
package com.ys.beanLife.bean;
import org.springframework.stereotype.Component;
@Component
public class A{
public A(B b) {
}
public A(B b, C c) {
}
}
package com.ys.beanLife;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Component;
@Component
public class ABeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition a = (GenericBeanDefinition) beanFactory.getBeanDefinition("a");
ConstructorArgumentValues values = new ConstructorArgumentValues();
ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder("1","java.lang.String");
values.addGenericArgumentValue(valueHolder);
a.setConstructorArgumentValues(values);
}
}
我们继续看原来的代码,具体的代码如下:
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 (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
// 将找到的构造函数赋值给candidates
Constructor<?>[] candidates = chosenCtors;
// 这儿等于null,因为笔者测试是第三种的情况
if (candidates == null) {
//先获取对应BeanClass
Class<?> beanClass = mbd.getBeanClass();
try {
//判断是否允许访问非公共的方法,默认是true
//获取所有的构造函数,这儿取出来就是一个默认的无参构造函数
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);
}
}
// Need to resolve the constructor.
// 这个值在这种情况下就是false,因为这两个条件都不成立
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
// 解析的构造参数的值
ConstructorArgumentValues resolvedValues = null;
//最小参数的个数
int minNrOfArgs;
//这个值默认为空的
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
//获取设置好的构造参数的值,这儿取出来的两个属性的长度应该都是1,这个方法的规则前面的博客有讲
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
//这个最小参数的值也是1,同时解析这个构造参数
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
//排序,排序的规则前面的博客笔者有讲
// pulic第一优先级,参数个数第二优先级
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
//有歧义的构造函数
Set<Constructor<?>> ambiguousConstructors = null;
//存放错误的集合
LinkedList<UnsatisfiedDependencyException> causes = null;
//遍历所有的传进来的构造函数
for (Constructor<?> candidate : candidates) {
//获取对应的构造函数的参数的个数
int parameterCount = candidate.getParameterCount();
//已经找到了要使用的构造函数和构造函数的参数,同时这个待使用的构造函数参数个数大于这个构造函数的参数的个数
//这个判断不成立
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
//如果这次的遍历的参数的个数小于最小使用的参数的个数,这个是不成立的,取出来的是2
if (parameterCount < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
//获取所有构造函数的参数的类型
Class<?>[] paramTypes = candidate.getParameterTypes();
//这个值默认情况下不等于null
if (resolvedValues != null) {
try {
//用于检查Java 6的{@link ConstructorProperties}的注解。
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);
}
//计算权重,前面的博客笔者有介绍
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
// 这儿计算出来的肯定满足,计算的结果是-1024,然后进行对应的赋值
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
//如果已经找的了待使用的构造函数的话,并且计算出来的权重等于最小的权重,这儿只遍历一次,所有这个判断是不会进的
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
//这儿表示没有找到待使用的构造函数,没有找到对应的构造函数
if (constructorToUse == null) {
//异常不等于空,直接组装异常,然后抛出
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
//直接抛出异常
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
//有歧义的构造函数不等于空的时候,同时是非宽松的模式的情况下,也是抛出异常
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
//传入参数等于空,同时argsHolderToUse不等于空的情况下,将这些东西缓存起来
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;
}
上面的在进行参数转换的时候,直接报错了,所以这第一种全部不满足的情况下,直接会报错。
我们再来看第二种,只有一个满足的,具体的代码测试代码如下:
package com.ys.beanLife.bean;
import org.springframework.stereotype.Component;
@Component
public class A{
public A(B b) {
}
public A(C c) {
}
}
package com.ys.beanLife;
import com.ys.test.B;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Component;
@Component
public class ABeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition a = (GenericBeanDefinition) beanFactory.getBeanDefinition("a");
ConstructorArgumentValues values = new ConstructorArgumentValues();
ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(new B(),"com.ys.beanLife.bean.B");
values.addGenericArgumentValue(valueHolder);
a.setConstructorArgumentValues(values);
}
}
我们继续看原来的代码,具体的代码如下:
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 (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
// 将找到的构造函数赋值给candidates
Constructor<?>[] candidates = chosenCtors;
// 这儿等于null,因为笔者测试是第三种的情况
if (candidates == null) {
//先获取对应BeanClass
Class<?> beanClass = mbd.getBeanClass();
try {
//判断是否允许访问非公共的方法,默认是true
//获取所有的构造函数,这儿取出来就是一个默认的无参构造函数
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);
}
}
// Need to resolve the constructor.
// 这个值在这种情况下就是false,因为这两个条件都不成立
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
// 解析的构造参数的值
ConstructorArgumentValues resolvedValues = null;
//最小参数的个数
int minNrOfArgs;
//这个值默认为空的
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
//获取设置好的构造参数的值,这儿取出来的两个属性的长度应该都是1,这个方法的规则前面的博客有讲
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
//这个最小参数的值也是1,同时解析这个构造参数
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
//排序,排序的规则前面的博客笔者有讲
// pulic第一优先级,参数个数第二优先级
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
//有歧义的构造函数
Set<Constructor<?>> ambiguousConstructors = null;
//存放错误的集合
LinkedList<UnsatisfiedDependencyException> causes = null;
//遍历所有的传进来的构造函数
for (Constructor<?> candidate : candidates) {
//获取对应的构造函数的参数的个数
int parameterCount = candidate.getParameterCount();
//已经找到了要使用的构造函数和构造函数的参数,同时这个待使用的构造函数参数个数大于这个构造函数的参数的个数
//这个判断不成立
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
//如果这次的遍历的参数的个数小于最小使用的参数的个数,这个是不成立的,取出来的是2
if (parameterCount < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
//获取所有构造函数的参数的类型
Class<?>[] paramTypes = candidate.getParameterTypes();
//这个值默认情况下不等于null
if (resolvedValues != null) {
try {
//用于检查Java 6的{@link ConstructorProperties}的注解。
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);
}
//计算权重,前面的博客笔者有介绍
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
// 这儿计算出来的肯定满足,计算的结果是-1024,然后进行对应的赋值
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
//如果已经找的了待使用的构造函数的话,并且计算出来的权重等于最小的权重,这儿只遍历一次,所有这个判断是不会进的
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
if (constructorToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
//有歧义的构造函数不等于空的时候,同时是非宽松的模式的情况下,也是抛出异常
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
//传入参数等于空,同时argsHolderToUse不等于空的情况下,将这些东西缓存起来
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;
}
这种情况,就是找到了对应的匹配的构造函数,然后调用对应的构造函数创建对象。
第三种情况,就是都满足的情况下,是选择哪个构造函数。具体的测试代码如下,其中B实现了I接口,但笔者测试发现,只有构造函数的参数的B的情况下是满足的,因为不是自动装配的情况下,是不会考虑接口和父类的情况,也就不会存在多种条件满足的情况,这种情况和第二种情况是一样的,但是如果开启的自动装配的情况下,调用的构造函数还是构造参数是B的那个,因为如果是接口的话,权重会加1,就是-1023了。就不是最小的权重了。
package com.ys.beanLife.bean;
import org.springframework.stereotype.Component;
@Component
public class A{
public A(B b) {
}
public A(I i) {
}
}
package com.ys.beanLife;
import com.ys.beanLife.bean.B;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Component;
@Component
public class ABeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition a = (GenericBeanDefinition) beanFactory.getBeanDefinition("a");
ConstructorArgumentValues values = new ConstructorArgumentValues();
ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(new B(),"com.ys.beanLife.bean.B","b");
values.addGenericArgumentValue(valueHolder);
a.setConstructorArgumentValues(values);
}
}
到此这个方法中的所有的情况都讲完了。
3.总结
- 推断的构造函数不为空的情况下:
- 提供一个构造函数加了
@Autowired
注解,不管这个构造函数有没有参数都是会直接调用这个构造函数创建对象的。 - 多个构造函数(只有一个构造函数添加了
@Autowired
注解),这个时候会调用这个加了@Autowired
注解的构造函数创建对象。 - 多个构造函数,每个构造函数都加了
@Autowired(required=false)
的注解,这个时候会调用参数个数最长的哪个构造函数,这儿所说的参数个数是指能在Spring容器中找到的参数个数。如果在非宽松的模式下,有两个构造函数(最长的参数个数的构造函数)的参数个数是相同的,并且计算的权重是一样。这个时候就会直接报错。至于什么是权重可以看前面的内容。如果在宽松的模式下,有两个构造函数(最长的参数个数的构造函数)的参数个数是相同,并且计算的权重是一样的。这个时候Spring会调用在源码顺序中靠前的构造函数。
- 推断的构造函数为空,但是提供的装配模型为构造器注入的情况下:
- 默认的无参的构造函数(没有加@Autowired注解),那么就会直接调用这个构造函数创建。
- 多个构造函数,没有提供@Autowired注解,这个时候会调用参数个数最长的哪个构造函数,这儿所说的参数个数是指能在Spring容器中找到的参数个数。如果在非宽松的模式下,有两个构造函数(最长的参数个数的构造函数)的参数个数是相同的,并且计算的权重是一样。这个时候就会直接报错。至于什么是权重可以看前面的内容。如果在宽松的模式下,有两个构造函数(最长的参数个数的构造函数)的参数个数是相同,并且计算的权重是一样的。这个时候Spring会调用在源码顺序中靠前的构造函数。
- 推断的构造函数为空,同时提供的装配模型不为构造器注入的,但是提供了构造函数参数的值情况下:
- 默认的无参的构造函数(没有加@Autowired注解),这个时候会直接报错
- 多个构造函数,没有提供@Autowired注解,这个时候是调用参数匹配的构造函数,注意如果B实现I,A中提供一个构造函数为A(I b),还有一个构造函数为A(B b)然后你提供的构造函数参数是B,同时类型是B.class,这个时候会直接调用A(B b)的构造函数,因为匹配的是相同的类型。但是如果这儿的装配模式是构造器注入的话,这个时候还会调用A(B b)的构造函数,因为计算权重A(B b)的构造函数的权重要小于A(I b)计算出来的权重。
4.写在最后
笔者主要讲了下对应autowireConstructor(beanName, mbd, ctors, args);
方法的调用的时机,以及各种情况下,会调用那个构造函数。实例化Bean还有最后一小部分就结束了。