5.x spring Fuente viaje veintiséis detallada getBean

Crear una unidad de parámetro de retención

He utilizado el ejemplo de dos métodos de fábrica, de hecho, sus diferencias son los mismos, se quejan, no importa, se analiza principalmente funciona el proceso:
Aquí Insertar imagen Descripción
Aquí Insertar imagen Descripción

Aquí Insertar imagen Descripción
En primer lugar, ir a buscar el nombre de la sonda parámetro de nombre de parámetro, de hecho, el interior es ASMcódigo de lectura de bytes de operar, sobre todo LocalVariableTableParameterNameDiscovererla clase, secuencia binaria para leer classel archivo, y luego analizar más compleja, está interesado puede ver. Nuestros métodos de análisis directamente en el núcleo de la misma.

createArgumentArray

Dejando un caso general, no incluye un xmlmodo de configuración o valores de los parámetros ajustada manualmente ConstructorArgumentValues, es la forma más común. El número de parámetros, atravesando parámetros, esto implicará el parámetro índice de paramIndexmateria, xmlno serán utilizados, en primer lugar, el método de fábrica (constructor) y se empaqueta en un índice común MethodParametertipo de tratamiento, seguido de montaje automático, analiza el objeto de parámetro , que es muy complicado, dijo que si bien el último en ser registrado y dependen depende bean, de hecho, no almacenar en caché, el siguiente puede ser utilizado directamente.

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;
	}

Un método de los parámetros de embalaje MethodParameter forExecutable

Esta es la planta de proceso para los métodos y constructores juntos en una forma común, para facilitar más tarde unitario.

	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);
		}
	}

constructor MethodParameter

De hecho, el método y el sistema de índice en, hay una capa anidada, como listen el anidado listesto, temporalmente no controlan, siendo que de acuerdo a lo general, la anidación es la capa que es 1, si no 1, volver a entrar para encontrar incrustado tipo de conjunto.

	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;
	}

parámetro analítico resolveAutowiredArgument montaje automático

En primer lugar, se juzga si el tipo de punto de inyección InjectionPoint, se describe un método de este tipo, o un parámetro constructor o atributo, ya que estos son los lugares se pueden inyectar de forma automática. Si es así, devuelve el acceso directo al punto de inyección, o dejar beanFactorya resolver las dependencias, antes de que, en primer MethodParameterencapsulado DependencyDescriptor, es decir, el punto de inyección.

	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

Juicio depende de qué tipo, para manejar diferentes tipos, por supuesto, estamos seguros es el último tipo de situación, nuestro tipo de encargo, ver si la carga diferida, si no llamar inmediatamente doResolveDependencypara resolver.

@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 obtener depende del tipo de getDependencyType

Si hay existe la propiedad y es mayor que los tipos anidados 1, se sabrá el tipo real, como List<String>presente, Stringel nido es 2, cierto tipo es String. Por supuesto, no somos una inyección de propiedad, por lo que una llamada directa MethodParameterde getNestedParameterType.

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

He encontrado una gran cantidad de código duplicado, de hecho, sobre todo con el procesamiento de la lógica de los mismos atributos, si sólo hay una capa, se llama directamente 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

Hay un tipo de retorno directo, u otro procesamiento se lleva a cabo para obtener el tipo de parámetro.

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;
	}

Pues bien, hoy aquí, esperamos estudio ayuda y entender, no rocíe el Gran Dios ver, comprender solamente su propio aprendizaje, capacidad limitada, por favor excusa.

Publicados 235 artículos originales · ganado elogios 74 · Vistas a 30000 +

Supongo que te gusta

Origin blog.csdn.net/wangwei19871103/article/details/105092170
Recomendado
Clasificación