Spring 构造推断源码浅析2

275 阅读3分钟

什么场景会进行第二次构造推断

		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        //1.第一次推断出来的构造不为空
        //2.自动注入模式为构造注入
        //这两种情况会进行第二次构造推断
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			return autowireConstructor(beanName, mbd, ctors, args);
		}

ConstructorResolver#autowireConstructor

public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
			@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {

		BeanWrapperImpl bw = new BeanWrapperImpl();
		this.beanFactory.initBeanWrapper(bw);
//需要被使用的 构造方法 
		Constructor<?> constructorToUse = null;
//构造方法的入参数组封装类        
		ArgumentsHolder argsHolderToUse = null;
//构造方法的入参数组        
		Object[] argsToUse = null;
        // explicitArgs 都为空
		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		else {
			Object[] argsToResolve = null;
			synchronized (mbd.constructorArgumentLock) {
            //判断 resolvedConstructorOrFactoryMethod 是否为空
            //和 constructorArgumentsResolved是否为true
            //这两个是什么意思,如果这个bd已经构造推断过这两个字段就会有值
            //使用的场景主要是原型模式,如果是单例的话,这两个都是不符合的
				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);
			}
		}
//如果 constructorToUse 等于null,说明构造还没被推断过,单例会到这里来
		if (constructorToUse == null || argsToUse == null) {
			// chosenCtors 是从后置处理器推断来的构造
			Constructor<?>[] candidates = chosenCtors;
			if (candidates == null) {
            //如果第一次推断的构造为空,就会获取所有的构造方法
				Class<?> beanClass = mbd.getBeanClass();
				try {
					candidates = (mbd.isNonPublicAccessAllowed() ?
							beanClass.getDeclaredConstructors() : beanClass.getConstructors());
				}
			}
//如果推断的只有一个构造或者只有一个构造,自动装配模式是构造
//而且这个构造是无参构造,就通过无参构造反射出对象
			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;
				}
			}

			// chosenCtors != null  说明第一次推断的参数是有值的
            //mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR
            //自动注入模式为构造注入
			boolean autowiring = (chosenCtors != null ||
					mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
			ConstructorArgumentValues resolvedValues = null;
            //最小参数个数
			int minNrOfArgs;
			if (explicitArgs != null) {
				minNrOfArgs = explicitArgs.length;
			}
			else {
				ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
				resolvedValues = new ConstructorArgumentValues();
				minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
			}
//对构造进行排序,排序方式优先级,比如根据public,private,根据构造方法的入参进行排序
//一般public在前面,构造方法的入参个数多的在前面
			AutowireUtils.sortConstructors(candidates);
            //最小差异权重为 integer的最大值
			int minTypeDiffWeight = Integer.MAX_VALUE;
			Set<Constructor<?>> ambiguousConstructors = null;
			LinkedList<UnsatisfiedDependencyException> causes = null;
//对候选的构造方法进行循环
			for (Constructor<?> candidate : candidates) {
            //获取构造方法的参数集合
				Class<?>[] paramTypes = candidate.getParameterTypes();
//如果可以用的构造和参数不为空,而且之前的构造的入参个数大于现在的入参个数,就是用之前的 
				if (constructorToUse != null && argsToUse != null && argsToUse.length > paramTypes.length) {
					// Already found greedy constructor that can be satisfied ->
					// do not look any further, there are only less greedy constructors left.
					break;
				}
                //如果参数个数小于最小参数个数 minNrOfArgs 默认为零,所以一般不满足
				if (paramTypes.length < minNrOfArgs) {
					continue;
				}

				ArgumentsHolder argsHolder;
                //resolvedValues 不为空,在上面已经new出来了
                //根据入参找出入参值,如果有入参在spring容器中找不到就continue出来
				if (resolvedValues != null) {
					try {
						String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
						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);
					}
				}
                //这个不会进去
				else {
					// Explicit arguments given -> arguments length must match exactly.
					if (paramTypes.length != explicitArgs.length) {
						continue;
					}
					argsHolder = new ArgumentsHolder(explicitArgs);
				}
//获取该构造方法的类型差异权重
				int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
						argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
				// 如果该类型差异权重比最小差异权重还小,说明满足,就设置到要被使用的构造字段里面
				if (typeDiffWeight < minTypeDiffWeight) {
					constructorToUse = candidate;
					argsHolderToUse = argsHolder;
					argsToUse = argsHolder.arguments;
					minTypeDiffWeight = typeDiffWeight;
					ambiguousConstructors = null;
				}
                //如果没有需要被使用的构造,而且最小差异权重跟当前差异权重一样
                //就把当前的构造放到  ambiguousConstructors 里面
				else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
					if (ambiguousConstructors == null) {
						ambiguousConstructors = new LinkedHashSet<>();
						ambiguousConstructors.add(constructorToUse);
					}
					ambiguousConstructors.add(candidate);
				}
			}
//如果最后构造为空,就抛出异常
			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)");
			}
            //ambiguousConstructors 存放差异权重相同的的构造
            //如果存在差异权重相同的构造,而且 isLenientConstructorResolution = false 就会抛出异常
			else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Ambiguous constructor matches found in bean '" + beanName + "' " +
						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
						ambiguousConstructors);
			}

			if (explicitArgs == null && argsHolderToUse != null) {
            //将推断出来的构造放到bd,方便原型模式的实例化
				argsHolderToUse.storeCache(mbd, constructorToUse);
			}
		}
//通过构造反射出对象
		Assert.state(argsToUse != null, "Unresolved constructor arguments");
		bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
		return bw;
	}



流程图: