我是靠谱客的博主 感性奇迹,最近开发中收集的这篇文章主要介绍解析属性注入规则,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

当容器在对属性进行依赖注入时,如果发现属性值需要进行类型转换,如属性值是容器中另一个Bean实例对象的引用,则容器首先需要根据属性值解析出所引用的对象,然后才能将该引用对象注入到目标实例对象的属性上去,对属性进行解析的由resolveValueIfNecessary()方法实现,其源码如下:

//解析属性值,对注入类型进行转换
@Nullable
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
	// We must check each value to see whether it requires a runtime reference
	// to another bean to be resolved.
	//对引用类型的属性进行解析
	if (value instanceof RuntimeBeanReference) {
		RuntimeBeanReference ref = (RuntimeBeanReference) value;
		//调用引用类型属性的解析方法
		return resolveReference(argName, ref);
	}
	//对属性值是引用容器中另一个Bean名称的解析
	else if (value instanceof RuntimeBeanNameReference) {
		String refName = ((RuntimeBeanNameReference) value).getBeanName();
		refName = String.valueOf(doEvaluate(refName));
		//从容器中获取指定名称的Bean
		if (!this.beanFactory.containsBean(refName)) {
			throw new BeanDefinitionStoreException(
					"Invalid bean name '" + refName + "' in bean reference for " + argName);
		}
		return refName;
	}
	//对Bean类型属性的解析,主要是Bean中的内部类
	else if (value instanceof BeanDefinitionHolder) {
		// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
		BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
		return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
	}
	else if (value instanceof BeanDefinition) {
		// Resolve plain BeanDefinition, without contained name: use dummy name.
		BeanDefinition bd = (BeanDefinition) value;
		String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
				ObjectUtils.getIdentityHexString(bd);
		return resolveInnerBean(argName, innerBeanName, bd);
	}
	//对集合数组类型的属性解析
	else if (value instanceof ManagedArray) {
		// May need to resolve contained runtime references.
		ManagedArray array = (ManagedArray) value;
		//获取数组的类型
		Class<?> elementType = array.resolvedElementType;
		if (elementType == null) {
			//获取数组元素的类型
			String elementTypeName = array.getElementTypeName();
			if (StringUtils.hasText(elementTypeName)) {
				try {
					//使用反射机制创建指定类型的对象
					elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
					array.resolvedElementType = elementType;
				}
				catch (Throwable ex) {
					// Improve the message by showing the context.
					throw new BeanCreationException(
							this.beanDefinition.getResourceDescription(), this.beanName,
							"Error resolving array type for " + argName, ex);
				}
			}
			//没有获取到数组的类型,也没有获取到数组元素的类型
			//则直接设置数组的类型为Object
			else {
				elementType = Object.class;
			}
		}
		//创建指定类型的数组
		return resolveManagedArray(argName, (List<?>) value, elementType);
	}
	//解析list类型的属性值
	else if (value instanceof ManagedList) {
		// May need to resolve contained runtime references.
		return resolveManagedList(argName, (List<?>) value);
	}
	//解析set类型的属性值
	else if (value instanceof ManagedSet) {
		// May need to resolve contained runtime references.
		return resolveManagedSet(argName, (Set<?>) value);
	}
	//解析map类型的属性值
	else if (value instanceof ManagedMap) {
		// May need to resolve contained runtime references.
		return resolveManagedMap(argName, (Map<?, ?>) value);
	}
	//解析props类型的属性值,props其实就是key和value均为字符串的map
	else if (value instanceof ManagedProperties) {
		Properties original = (Properties) value;
		//创建一个拷贝,用于作为解析后的返回值
		Properties copy = new Properties();
		original.forEach((propKey, propValue) -> {
			if (propKey instanceof TypedStringValue) {
				propKey = evaluate((TypedStringValue) propKey);
			}
			if (propValue instanceof TypedStringValue) {
				propValue = evaluate((TypedStringValue) propValue);
			}
			if (propKey == null || propValue == null) {
				throw new BeanCreationException(
						this.beanDefinition.getResourceDescription(), this.beanName,
						"Error converting Properties key/value pair for " + argName + ": resolved to null");
			}
			copy.put(propKey, propValue);
		});
		return copy;
	}
	//解析字符串类型的属性值
	else if (value instanceof TypedStringValue) {
		// Convert value to target type here.
		TypedStringValue typedStringValue = (TypedStringValue) value;
		Object valueObject = evaluate(typedStringValue);
		try {
			//获取属性的目标类型
			Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
			if (resolvedTargetType != null) {
				//对目标类型的属性进行解析,递归调用
				return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
			}
			//没有获取到属性的目标对象,则按Object类型返回
			else {
				return valueObject;
			}
		}
		catch (Throwable ex) {
			// Improve the message by showing the context.
			throw new BeanCreationException(
					this.beanDefinition.getResourceDescription(), this.beanName,
					"Error converting typed String value for " + argName, ex);
		}
	}
	else if (value instanceof NullBean) {
		return null;
	}
	else {
		return evaluate(value);
	}
}
//解析引用类型的属性值
@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
	try {
		Object bean;
		//获取引用的Bean名称
		String refName = ref.getBeanName();
		refName = String.valueOf(doEvaluate(refName));
		//如果引用的对象在父类容器中,则从父类容器中获取指定的引用对象
		if (ref.isToParent()) {
			if (this.beanFactory.getParentBeanFactory() == null) {
				throw new BeanCreationException(
						this.beanDefinition.getResourceDescription(), this.beanName,
						"Can't resolve reference to bean '" + refName +
						"' in parent factory: no parent factory available");
			}
			bean = this.beanFactory.getParentBeanFactory().getBean(refName);
		}
		//从当前的容器中获取指定的引用Bean对象,如果指定的Bean没有被实例化
		//则会递归触发引用Bean的初始化和依赖注入
		else {
			bean = this.beanFactory.getBean(refName);
			//将当前实例化对象的依赖引用对象
			this.beanFactory.registerDependentBean(refName, this.beanName);
		}
		if (bean instanceof NullBean) {
			bean = null;
		}
		return bean;
	}
	catch (BeansException ex) {
		throw new BeanCreationException(
				this.beanDefinition.getResourceDescription(), this.beanName,
				"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
	}
}
//解析array类型的属性
private Object resolveManagedArray(Object argName, List<?> ml, Class<?> elementType) {
	//创建一个指定类型的数组,用于存放和返回解析后的数组
	Object resolved = Array.newInstance(elementType, ml.size());
	for (int i = 0; i < ml.size(); i++) {
		//递归解析array的每一个元素,并将解析后的值设置到resolved数组中,索引为i
		Array.set(resolved, i,
				resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
	}
	return resolved;
}

通过上面的代码分析,我们明白了Spring 是如何将引用类型,内部类以及集合类型等属性进行解析的,属性值解析完成后就可以进行依赖注入了,依赖注入的过程就是Bean 对象实例设置到它所依赖的Bean对象属性上去。而真正的依赖注入是通过bw.setPropertyValues()方法实现的,该方法也使用了委托模式, 在BeanWrapper 接口中至少定义了方法声明, 依赖注入的具体实现交由其实现类BeanWrapperImpl 来完成,下面我们就分析依BeanWrapperImpl 中赖注入相关的源码。

 

最后

以上就是感性奇迹为你收集整理的解析属性注入规则的全部内容,希望文章能够帮你解决解析属性注入规则所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部