注入赋值

BeanWrapperImpl 类主要是对容器中完成初始化的Bean 实例对象进行属性的依赖注入,即把Bean对象设置到它所依赖的另一个Bean 的属性中去。然而,BeanWrapperImpl 中的注入方法实际上由AbstractNestablePropertyAccessor 来实现的,其相关源码如下:

//实现属性依赖注入功能
protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
	if (tokens.keys != null) {
		processKeyedProperty(tokens, pv);
	}
	else {
		processLocalProperty(tokens, pv);
	}
}
//实现属性依赖注入功能
@SuppressWarnings("unchecked")
private void processKeyedProperty(PropertyTokenHolder tokens, PropertyValue pv) {
	//调用属性的getter方法,获取属性的值
	Object propValue = getPropertyHoldingValue(tokens);
	PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
	if (ph == null) {
		throw new InvalidPropertyException(
				getRootClass(), this.nestedPath + tokens.actualName, "No property handler found");
	}
	Assert.state(tokens.keys != null, "No token keys");
	String lastKey = tokens.keys[tokens.keys.length - 1];

	//注入array类型的属性值
	if (propValue.getClass().isArray()) {
		Class<?> requiredType = propValue.getClass().getComponentType();
		int arrayIndex = Integer.parseInt(lastKey);
		Object oldValue = null;
		try {
			if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
				oldValue = Array.get(propValue, arrayIndex);
			}
			Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
					requiredType, ph.nested(tokens.keys.length));
			//获取集合类型属性的长度
			int length = Array.getLength(propValue);
			if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {
				Class<?> componentType = propValue.getClass().getComponentType();
				Object newArray = Array.newInstance(componentType, arrayIndex + 1);
				System.arraycopy(propValue, 0, newArray, 0, length);
				setPropertyValue(tokens.actualName, newArray);
				//调用属性的getter方法,获取属性的值
				propValue = getPropertyValue(tokens.actualName);
			}
			//将属性的值赋值给数组中的元素
			Array.set(propValue, arrayIndex, convertedValue);
		}
		catch (IndexOutOfBoundsException ex) {
			throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
					"Invalid array index in property path '" + tokens.canonicalName + "'", ex);
		}
	}

	//注入list类型的属性值
	else if (propValue instanceof List) {
		//获取list集合的类型
		Class<?> requiredType = ph.getCollectionType(tokens.keys.length);
		List<Object> list = (List<Object>) propValue;
		//获取list集合的size
		int index = Integer.parseInt(lastKey);
		Object oldValue = null;
		if (isExtractOldValueForEditor() && index < list.size()) {
			oldValue = list.get(index);
		}
		//获取list解析后的属性值
		Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
				requiredType, ph.nested(tokens.keys.length));
		int size = list.size();
		//如果list的长度大于属性值的长度,则多余的元素赋值为null
		if (index >= size && index < this.autoGrowCollectionLimit) {
			for (int i = size; i < index; i++) {
				try {
					list.add(null);
				}
				catch (NullPointerException ex) {
					throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
							"Cannot set element with index " + index + " in List of size " +
							size + ", accessed using property path '" + tokens.canonicalName +
							"': List does not support filling up gaps with null elements");
				}
			}
			list.add(convertedValue);
		}
		else {
			try {
				//将值添加到list中
				list.set(index, convertedValue);
			}
			catch (IndexOutOfBoundsException ex) {
				throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
						"Invalid list index in property path '" + tokens.canonicalName + "'", ex);
			}
		}
	}

	//注入map类型的属性值
	else if (propValue instanceof Map) {
		//获取map集合key的类型
		Class<?> mapKeyType = ph.getMapKeyType(tokens.keys.length);
		//获取map集合value的类型
		Class<?> mapValueType = ph.getMapValueType(tokens.keys.length);
		Map<Object, Object> map = (Map<Object, Object>) propValue;
		// IMPORTANT: Do not pass full property name in here - property editors
		// must not kick in for map keys but rather only for map values.
		TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(mapKeyType);
		//解析map类型属性key值
		Object convertedMapKey = convertIfNecessary(null, null, lastKey, mapKeyType, typeDescriptor);
		Object oldValue = null;
		if (isExtractOldValueForEditor()) {
			oldValue = map.get(convertedMapKey);
		}
		// Pass full property name and old value in here, since we want full
		// conversion ability for map values.
		//解析map类型属性value值
		Object convertedMapValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
				mapValueType, ph.nested(tokens.keys.length));
		//将解析后的key和value值赋值给map集合属性
		map.put(convertedMapKey, convertedMapValue);
	}

	else {
		throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
				"Property referenced in indexed property path '" + tokens.canonicalName +
				"' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
	}
}
private Object getPropertyHoldingValue(PropertyTokenHolder tokens) {
	// Apply indexes and map keys: fetch value for all keys but the last one.
	Assert.state(tokens.keys != null, "No token keys");
	PropertyTokenHolder getterTokens = new PropertyTokenHolder(tokens.actualName);
	getterTokens.canonicalName = tokens.canonicalName;
	getterTokens.keys = new String[tokens.keys.length - 1];
	System.arraycopy(tokens.keys, 0, getterTokens.keys, 0, tokens.keys.length - 1);

	Object propValue;
	try {
		//获取属性值
		propValue = getPropertyValue(getterTokens);
	}
	catch (NotReadablePropertyException ex) {
		throw new NotWritablePropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
				"Cannot access indexed value in property referenced " +
				"in indexed property path '" + tokens.canonicalName + "'", ex);
	}

	if (propValue == null) {
		// null map value case
		if (isAutoGrowNestedPaths()) {
			int lastKeyIndex = tokens.canonicalName.lastIndexOf('[');
			getterTokens.canonicalName = tokens.canonicalName.substring(0, lastKeyIndex);
			propValue = setDefaultValue(getterTokens);
		}
		else {
			throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + tokens.canonicalName,
					"Cannot access indexed value in property referenced " +
					"in indexed property path '" + tokens.canonicalName + "': returned null");
		}
	}
	return propValue;
}

通过对上面注入依赖代码的分析,我们已经明白了Spring IOC 容器是如何将属性的值注入到Bean 实例对象中去的:

1)、对于集合类型的属性,将其属性值解析为目标类型的集合后直接赋值给属性。

2)、对于非集合类型的属性,大量使用了JDK 的反射机制,通过属性的getter()方法获取指定属性注入以前的值,同时调用属性的setter()方法为属性设置注入后的值。看到这里相信很多人都明白了Spring的setter()注入原理。

至此Spring IOC 容器对Bean 定义资源文件的定位,载入、解析和依赖注入已经全部分析完毕,现在Spring IOC 容器中管理了一系列靠依赖关系联系起来的Bean,程序不需要应用自己手动创建所需的对象,Spring IOC 容器会在我们使用的时候自动为我们创建,并且为我们注入好相关的依赖,这就是Spring 核心功能的控制反转和依赖注入的相关功能。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值