随笔分类
autowireConstructor
构造函数的自动注入
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
/** 使用 ConstructorResolver来代理实现 **/
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
/**
* 总结:
* 这里主要做了三件事:
* 1.构造参数的确定
* getBean时是否传了 args
* 尝试从缓存中去获取参数(缓存中缓存的可能是参数的初始类型,也有可能是参数的最终类型,因此这里会进行解析)
* 以上都没有拿到构造参数的话,则会进行从配置文件中获取并来解析参数了
* 2.构造函数的确定
* 尝试从缓存中去获取 bd中解析后的构造器(第一次解析后,会缓存起来,以来提高程序性能)
* 缓存中获取不到, 则会根据已经确定的构造参数个数、类型来去匹配 bd中对应的所有可访问的构造器(这里会进行匹配),最终获取到一个最为匹配的构造器
* 3.根据已经确定的构造参数、筛选出来的构造器,进行反射创建 bean实例
*/
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors /** 构造器集合,可能是 null,也可能不是 null **/, @Nullable Object[] explicitArgs /** 这里通常是 null **/) {
/** BeanWrapper的实现类 **/
BeanWrapperImpl bw = new BeanWrapperImpl();
/**
* 这里干了两件事:(不是很重要...)
* 1. 向 wrapper中注册了 conversion
* 2. 向 wrapper中注册了 属性编辑器
*/
this.beanFactory.initBeanWrapper(bw);
/** constructorToUse 表示实例化时反射要去调用的构造器 **/
Constructor<?> constructorToUse = null;
/** argsHolderToUse 表示实例化时要去使用的参数的持有对象 **/
ArgumentsHolder argsHolderToUse = null;
/** argsToUse 表示实例化时要去使用的参数 **/
Object[] argsToUse = null;
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
/** 如果 getBean时没有指定 args的话,则会尝试从配置文件中进行解析 **/
/** 通会来到这,这也是我们欲要分析的路线 **/
/** 保存需要做转换的构造参数的引用 **/
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
/** 尝试从缓存中拿已经解析过的构造函数 --> 缓存机制,之前分析过了 **/
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
/** true -> 从缓存中拿到了构造函数并且对应的构造参数已经被解析过了,那就直接拿来进行反射创建实例即可 **/
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
/**
* 来到这,此处的 resolvedConstructorArguments以及 preparedConstructorArguments一定有一个不空
*/
// Found a cached constructor...
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
/** 如果 resolvedConstructorArguments 为空,此处便会成立,赋值为 preparedConstructorArguments **/
/** 可以将 preparedConstructorArguments视为保存的是未完全解析成功的 参数集合,需要进行进一步的解析才能被使用 **/
if (argsToResolve != null) {
/** 缓存中的值可能是原始值,也可能是最终值 **/
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
}
}
/** 条件成立, 说明上面的缓存机制失败,需要进行构造器匹配逻辑... autowireConstructor **/
if (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
/** 构造方法上有 @Autowired注解时,chosenCtors才会有数据 **/
/** candidates存放可选项的构造器 **/
Constructor<?>[] candidates = chosenCtors;
/** 条件成立, 说明外部程序调用 autowiredConstructor时并没有提供可选用的 构造器... 因此,需要通过 Class拿到构造器信息 **/
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
/** 根据 mbd中的权限信息决定拿的是 所有已经声明的构造器还是 仅仅是公开的构造器 **/
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;
}
/** instantiate 使用无参构造器完成反射调用,创建出来实例对象 **/
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
// Need to resolve the constructor.
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
/** 表示解析后的构造器参数值列表 **/
ConstructorArgumentValues resolvedValues = null;
/** 表示构造器参数个数 **/
int minNrOfArgs;
/** 不考虑 args != null 的情况 **/
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
/** 获取构造器参数个数 **/
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
/** 给可选用的构造器进行排序 **/
/** 排序规则:public > 非公开 > 参数多的 > 参数少的 **/
AutowireUtils.sortConstructors(candidates);
/** 比较重要的一个值 **/
/** 这个值越低,说明当前的构造器参数列表类型和当前的构造器参数匹配度越高,反之,这个值越高,说明当前构造器参数列表类型和构造器参数匹配度越低 **/
int minTypeDiffWeight = Integer.MAX_VALUE;
/** 表示模棱两可的构造器 -> 假设第二个构造器的 diffWeight值与上一个一致,则将其放入到该集合中 **/
Set<Constructor<?>> ambiguousConstructors = null;
Deque<UnsatisfiedDependencyException> causes = null;
/** 筛选可选项构造器,找出 最为匹配的构造器 (minTypeDiffWeight最低) **/
for (Constructor<?> candidate : candidates) {
/** 获取当前处理的构造器参数个数 **/
int parameterCount = candidate.getParameterCount();
/**
* candidates是排过序的,越往后优先级就越低
* 当出现已经存在适合的构造器并且当前迭代的构造器参数数目小于已经适合的构造器,此时就没有必要继续执行操作了
*/
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;
}
/** true -> 当前迭代的构造器不匹配,直接下一个 **/
if (parameterCount /** 表示当前迭代的构造器参数个数 **/ < minNrOfArgs /** 表示 bd中配置的构造器参数个数 **/) {
continue;
}
// 表示构造器参数的持有对象
ArgumentsHolder argsHolder;
// paramTypes 表示当前迭代的构造器的参数类型列表
Class<?>[] paramTypes = candidate.getParameterTypes();
/** true -> 说明 bd中已经有解析后的参数值了 **/
if (resolvedValues != null) {
try {
/**
* @ConstructorProperties 该注释用于构造函数上,显示该构造函数的参数和 getter方法想对应
* 由于方法参数名在运行时不可见,如果没有标注的话就没有办法知道参数是否符合 参数对应的 get方法了
* 因此,当使用 Spring的构造参数名称进行初始化 bean时,需要在构造函数上加该注释
*/
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
/** true -> 说明没有在构造器上加上 @ConstructorProperties注解 **/
/** 如:public student(String name, int age) **/
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate); // 这里获取到的会是 ["name", "age"]
}
}
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 ArrayDeque<>(1);
}
causes.add(ex);
continue;
}
}
/** 说明 bd中并没有配置解析后的参数值 **/
else {
// Explicit arguments given -> arguments length must match exactly.
if (parameterCount != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
/**
* lenientConstructorResolution -> true, 宽松策略,ambiguousConstructors中允许有值
* lenientConstructorResolution -> false, 狭窄策略,ambiguousConstructors不允许有值, 否则的话这里会报错
* 这里会计算出构造器参数类型与参数类型的一个匹配度
*/
int typeDiffWeight = (mbd.isLenientConstructorResolution() /** 来判断是否宽松策略?还是狭窄策略? **/?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
/** 条件成立,说明当前迭代的构造器比上一次筛选出来的构造器更优先 **/
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
/** 更新当前的最小值 **/
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
/** 条件成立的话,说明当前处理的构造器计算出来的 匹配度和上一次筛选计算出来的匹配度一致... 说明有模棱两可的情况... **/
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
} /** 迭代结束 **/
/** 未找到可以使用的构造器,只能报错了 **/
if (constructorToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor " +
"(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);
}
/** true, 说明构造器自动匹配成功了,需要进行缓存,方便后来者... 再次使用该 bd实例化 **/
if (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
Assert.state(argsToUse != null, "Unresolved constructor arguments");
/** 根据上述筛选以及计算出来的构造器和解析出来的参数 进行反射创建实例 **/
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
initBeanWrapper
这个方法可以忽略,不影响理解
protected void initBeanWrapper(BeanWrapper bw) {
bw.setConversionService(getConversionService() /** 类型转换器 **/);
/** 来注册一些属性编辑器 **/
registerCustomEditors(bw);
}
getTypeDifferenceWeight
进行类型比较,计算出匹配度
public static int getTypeDifferenceWeight(Class<?>[] paramTypes, Object[] args) {
int result = 0;
for (int i = 0; i < paramTypes.length; i++) {
/** 这里比较的其实是构造器参数类型与实际参数的类型的匹配,这里是进行类型继承关系的判定,若二者类型之间没有继承关系的话,那么匹配度就很低了 **/
if (!ClassUtils.isAssignableValue(paramTypes[i], args[i])) {
return Integer.MAX_VALUE;
}
/**
* 这里做的其实就是进行参数类型的匹配,匹配的过程中根据疏远关系来计算匹配度
* 没有继承关系,匹配度最低
* 继承关系近,匹配度不高
* 继承关系远,匹配度较高
*/
if (args[i] != null) {
Class<?> paramType = paramTypes[i];
Class<?> superClass = args[i].getClass().getSuperclass();
while (superClass != null) {
if (paramType.equals(superClass)) {
result = result + 2;
superClass = null;
}
else if (ClassUtils.isAssignable(paramType, superClass)) {
result = result + 2;
superClass = superClass.getSuperclass();
}
else {
superClass = null;
}
}
if (paramType.isInterface()) {
result = result + 1;
}
}
}
return result;
}
instantiate
private Object instantiate(
String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) {
try {
/** 获取实例化策略 **/
InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),
this.beanFactory.getAccessControlContext());
}
else {
/** 根据获取的策略去创建 bean **/
return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via constructor failed", ex);
}
}
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
final Constructor<?> ctor, Object... args) {
/** 这里来判断有没有方法覆盖的场景 **/
/** 我们主要来考虑没有没有方法覆盖的场景 **/
if (!bd.hasMethodOverrides()) {
if (System.getSecurityManager() != null) {
// use own privileged to change accessibility (when security is on)
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(ctor);
return null;
});
}
return BeanUtils.instantiateClass(ctor, args);
}
/** 这里是有方法覆盖的场景 **/
/** 如果存在有需要替换或者动态代理的方法,就不能直接使用反射来进行创建了,此时需要使用 cglib进行动态代理,因为动态代理时可以将动态方法织入类中 **/
else {
return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
}
}
instantiateClass
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
ReflectionUtils.makeAccessible(ctor);
if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
return KotlinDelegate.instantiateClass(ctor, args);
}
/** 我们主要来分析这条路径 **/
else {
Class<?>[] parameterTypes = ctor.getParameterTypes();
Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
/** 这里是创建了新的参数数组,主要是为了预防一些特殊场景:无默认值, 传 null的场景 **/
Object[] argsWithDefaultValues = new Object[args.length];
for (int i = 0 ; i < args.length; i++) {
/** 如果参数解析出来是 null的情况 **/
if (args[i] == null) {
Class<?> parameterType = parameterTypes[i];
argsWithDefaultValues[i] = (parameterType.isPrimitive() /** 判断参数类型是不是基本的数据类型 **/? DEFAULT_TYPE_VALUES.get(parameterType) : null);
}
else {
argsWithDefaultValues[i] = args[i];
}
}
/** 来了,它来了,这里就是实质性的调用 构造器传递参数反射来创建实例 bean的方法了!!! **/
return ctor.newInstance(argsWithDefaultValues);
}
}
catch (InstantiationException ex) {
throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
}
catch (InvocationTargetException ex) {
throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
}
}