spring(五)类型转换

类型转换

之前在介绍bean的创建过程中,其中有一步是调用populateBean,来将BeanDefinition中的PropertyValue来设置到bean中
因为在xml中标签中指定的值都为字符串类型,所以需要进行类型转换,将字符串类型的值转换为bean对应属性的类型
在populateBean中最后会调用applyPropertyValues来将PropertyValue中的属性值设置到创建的bean实例中

// AbstractAutowireCapableBeanFactory
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
   
	if (pvs != null) {
   
		applyPropertyValues(beanName, mbd, bw, pvs);
	}
}

在调用applyPropertyValues的过程中,会遍历PropertyValues中的所有属性,然后调用convertForProperty进行类型转换

// AbstractAutowireCapableBeanFactory
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
   
	// 省略
	// 判断是否使用了自定义的类型转换器
	// 如果没有指定,那么会使用BeanWrapper作为类型转换器
	TypeConverter converter = getCustomTypeConverter();
	if (converter == null) {
   
		converter = bw;
	}
	List<PropertyValue> deepCopy = new ArrayList<>(original.size());
	boolean resolveNecessary = false;
	for (PropertyValue pv : original) {
   
		// 如果已经转换过,直接添加到deepCopy中
		if (pv.isConverted()) {
   
			deepCopy.add(pv);
		}
		else {
   
			String propertyName = pv.getName();
			Object originalValue = pv.getValue();
			if (originalValue == AutowiredPropertyMarker.INSTANCE) {
   
				Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
				if (writeMethod == null) {
   
					throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
				}
				originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
			}
			Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
			Object convertedValue = resolvedValue;
			boolean convertible = bw.isWritableProperty(propertyName) &&
					!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
			if (convertible) {
   
				// 进行转换
				convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
			}
			// Possibly store converted value in merged bean definition,
			// in order to avoid re-conversion for every created bean instance.
			if (resolvedValue == originalValue) {
   
				if (convertible) {
   
					pv.setConvertedValue(convertedValue);
				}
				deepCopy.add(pv);
			}
			else if (convertible && originalValue instanceof TypedStringValue &&
					!((TypedStringValue) originalValue).isDynamic() &&
					!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
   
				pv.setConvertedValue(convertedValue);
				deepCopy.add(pv);
			}
			else {
   
				resolveNecessary = true;
				deepCopy.add(new PropertyValue(pv, convertedValue));
			}
		}
	}
}

下面主要看下convertForProperty做了什么

private Object convertForProperty(
			@Nullable Object value, String propertyName, BeanWrapper bw, TypeConverter converter) {
   
	// 如果传入的Converter是BeanWrapperImpl,那么会调用BeanWrapperImpl的convertForProperty来进行类型的转换
	if (converter instanceof BeanWrapperImpl) {
   
		return ((BeanWrapperImpl) converter).convertForProperty(value, propertyName);
	}
	else {
   
		// 否则会调用TypeConvertor的convertIfNecessary来进行类型的转换
		PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
		MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
		return converter.convertIfNecessary(value, pd.getPropertyType(), methodParam);
	}
}

TypeConverter.convertIfNecessary

下面首先看下走TypeConverter.convertIfNecessary这个分支
convertIfNecessary方法主要由DateBinder和TypeConverterSupport两个类来实现,这里主要看下TypeConverterSupport

// TypeConverterSupport
public <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType,
			@Nullable TypeDescriptor typeDescriptor) throws TypeMismatchException {
   

	Assert.state(this.typeConverterDelegate != null, "No TypeConverterDelegate");
	try {
   
		return this.typeConverterDelegate.convertIfNecessary(null, null, value, requiredType, typeDescriptor);
	}
	catch (ConverterNotFoundException | IllegalStateException ex) {
   
		throw new</
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值