20、Spring5.x源码之旅二十getBean详解六

  • 创建参数持有器
    • createArgumentArray
    • MethodParameter的forExecutable封装方法参数
      • MethodParameter的构造方法
    • resolveAutowiredArgument解析自动装配参数
      • DefaultListableBeanFactory的resolveDependency
      • MethodParameter的getDependencyType获取依赖类型
      • MethodParameter的getNestedParameterType
        • DependencyDescriptor的getNestedParameterType

创建参数持有器

我就用两个工厂方法来做例子,其实他们差异是一样的,会报错,没关系,我们主要分析过程原理:
*
*

*
首先会用参数名字探测器去获取参数的名字,其实内部是用ASM读取字节码来操作的,主要是LocalVariableTableParameterNameDiscoverer这个类,二进制流读取class文件,然后分析,比较复杂,有兴趣的可以去看。我们直接就核心方法分析吧。

createArgumentArray

留下了一般的情况,不包括用xml方式设置参数值或者手动设置了ConstructorArgumentValues,就是最普通的形式。根据参数的数量,开始遍历参数,这里就会涉及参数的索引paramIndex 啦,xml里会用到,首先将工厂方法(构造方法)和索引封装成一个通用的MethodParameter类型处理,然后进行自动装配,解析出参数对象,里面很复杂,一会儿说,最后要注册依赖和被依赖的bean,其实就是做缓存,下次可以直接用。

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);//装配的bean名字
		//带参数的话
		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) {
   
     
				...
			}
			if (valueHolder != null) {
   
     
				...
			}
			else {
   
     
				//获取统一的方法参数类型
				MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);

				if (!autowiring) {
   
     
					throw new UnsatisfiedDependencyException(
					...
				}
				try {
   
     //解析自动装配参数,找到会进行实例化
					Object autowiredArgument = resolveAutowiredArgument(
							methodParam, beanName, autowiredBeanNames, converter, fallback);
					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);
				}
			}
		}
		//注册依赖的bean
		for (String autowiredBeanName : autowiredBeanNames) {
   
     
			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;
	}

MethodParameter的forExecutable封装方法参数

这里就是将工厂方法和构造方法一起处理成通用形式,方便后面统一处理。

	public static MethodParameter forExecutable(Executable executable, int parameterIndex) {
   
     
		if (executable instanceof Method) {
   
     
			return new MethodParameter((Method) executable, parameterIndex);
		}
		else if (executable instanceof Constructor) {
   
     
			return new MethodParameter((Constructor<?>) executable, parameterIndex);
		}
		else {
   
     
			throw new IllegalArgumentException("Not a Method/Constructor: " + executable);
		}
	}

MethodParameter的构造方法

其实就是把方法和索引设置进去,还有一个嵌套层,比如list里嵌套list这种,暂时不用管,我们还是按一般的来,嵌套就是层就是1,如果不是1,后面会去查找内部的嵌套类型。

	public MethodParameter(Method method, int parameterIndex, int nestingLevel) {
   
     
		Assert.notNull(method, "Method must not be null");
		this.executable = method;
		this.parameterIndex = validateIndex(method, parameterIndex);
		this.nestingLevel = nestingLevel;
	}

resolveAutowiredArgument解析自动装配参数

首先判断是否是注入点类型InjectionPoint ,这个类型就是描述一个方法或者构造器的参数或者一个属性,因为这些都是可以自动注入的地方。如果是的话,就直接获取注入点返回,否则就让beanFactory来解析依赖,在这之前,先把MethodParameter 封装成DependencyDescriptor,也就是注入点。

	protected Object resolveAutowiredArgument(MethodParameter param, String beanName,
			@Nullable Set<String> autowiredBeanNames, TypeConverter typeConverter, boolean fallback) {
   
     

		Class<?> paramType = param.getParameterType();
		if (InjectionPoint.class.isAssignableFrom(paramType)) {
   
     //是否是注入点类型,比如DependencyDescriptor
			InjectionPoint injectionPoint = currentInjectionPoint.get();
			if (injectionPoint == null) {
   
     
				throw new IllegalStateException("No current InjectionPoint available for " + param);
			}
			return injectionPoint;
		}
		try {
   
     //beanFactory解析依赖
			return this.beanFactory.resolveDependency(
					new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
		}
		catch (NoUniqueBeanDefinitionException ex) {
   
     
			throw ex;
		}
		catch (NoSuchBeanDefinitionException ex) {
   
     
			if (fallback) {
   
     
				...
			}
			throw ex;
		}
	}

DefaultListableBeanFactory的resolveDependency

判断依赖是什么类型,根据不同类型来处理,当然我们肯定是最后的那种情况,我们自定义的类型,看看是否是懒加载的,如果不是就立即调用doResolveDependency来解析。

@Override
	@Nullable
	public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
   
     
		//设置参数名字探索器
		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
		if (Optional.class == descriptor.getDependencyType()) {
   
     //Optional类型
			return createOptionalDependency(descriptor, requestingBeanName);
		}//是对象工厂类型或者对象提供者类型
		else if (ObjectFactory.class == descriptor.getDependencyType() ||
				ObjectProvider.class == descriptor.getDependencyType()) {
   
     
			return new DependencyObjectProvider(descriptor, requestingBeanName);
		}//java扩展的注入类
		else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
   
     
			return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
		}
		else {
   
     //我们自己只能的类型,先看是否是懒加载,是的话就直接返回,否则要去解析依赖
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
					descriptor, requestingBeanName);
			if (result == null) {
   
     
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}

MethodParameter的getDependencyType获取依赖类型

这里如果有属性存在,而且嵌套类型大于1,就会找出真实类型,比如List<String>这种,String的嵌套就是2,真实类型就是String。当然我们不是属性注入,所以直接调用MethodParametergetNestedParameterType

public Class<?> getDependencyType() {
   
     
		if (this.field != null) {
   
     
			if (this.nestingLevel > 1) {
   
     
				Type type = this.field.getGenericType();
				for (int i = 2; i <= this.nestingLevel; i++) {
   
     
					if (type instanceof ParameterizedType) {
   
     
						Type[] args = ((ParameterizedType) type).getActualTypeArguments();
						type = args[args.length - 1];
					}
				}
				if (type instanceof Class) {
   
     
					return (Class<?>) type;
				}
				else if (type instanceof ParameterizedType) {
   
     
					Type arg = ((ParameterizedType) type).getRawType();
					if (arg instanceof Class) {
   
     
						return (Class<?>) arg;
					}
				}
				return Object.class;
			}
			else {
   
     
				return this.field.getType();
			}
		}
		else {
   
     
			return obtainMethodParameter().getNestedParameterType();
		}
	}

MethodParameter的getNestedParameterType

发现了大量重复代码,其实大部分是跟属性的处理逻辑一样的,如果只有1层,就直接调用getParameterType

public Class<?> getNestedParameterType() {
   
     
		if (this.nestingLevel > 1) {
   
     
			Type type = getGenericParameterType();
			for (int i = 2; i <= this.nestingLevel; i++) {
   
     
				if (type instanceof ParameterizedType) {
   
     
					Type[] args = ((ParameterizedType) type).getActualTypeArguments();
					Integer index = getTypeIndexForLevel(i);
					type = args[index != null ? index : args.length - 1];
				}
				// TODO: Object.class if unresolvable
			}
			if (type instanceof Class) {
   
     
				return (Class<?>) type;
			}
			else if (type instanceof ParameterizedType) {
   
     
				Type arg = ((ParameterizedType) type).getRawType();
				if (arg instanceof Class) {
   
     
					return (Class<?>) arg;
				}
			}
			return Object.class;
		}
		else {
   
     
			return getParameterType();
		}
	}

DependencyDescriptor的getNestedParameterType

存在类型就直接返回了,否则就要进行其他处理获得参数类型。

public Class<?> getParameterType() {
   
     
		Class<?> paramType = this.parameterType;
		if (paramType != null) {
   
     
			return paramType;
		}
		if (getContainingClass() != getDeclaringClass()) {
   
     
			paramType = ResolvableType.forMethodParameter(this, null, 1).resolve();
		}
		if (paramType == null) {
   
     
			paramType = computeParameterType();
		}
		this.parameterType = paramType;
		return paramType;
	}

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。