spring(五)类型转换

本文深入探讨了Spring中的类型转换过程,从`TypeConverter.convertIfNecessary`到`GenericConversionService.convert`,涉及`BeanWrapperImpl`、`TypeConverterDelegate`和`ConversionService`等关键组件。还介绍了`Converter`的注册方法,包括`addConverter`系列方法,并提到了如何通过`ConversionServiceFactoryBean`注册自定义转换器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

类型转换

之前在介绍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 ConversionNotSupportedException(value, requiredType, ex);
	}
	catch (ConversionException | IllegalArgumentException ex) {
		throw new TypeMismatchException(value, requiredType, ex);
	}
}

可以看到主要是调用TypeConverterDelegate的convertIfNecessary来完成的

BeanWrapperImpl.convertForProperty

// BeanWrapperImpl
public Object convertForProperty(@Nullable Object value, String propertyName) throws TypeMismatchException {
	// 在进行属性转换之前,增加了对PropertyDescriptor和TypeDescriptor的缓存
	CachedIntrospectionResults cachedIntrospectionResults = getCachedIntrospectionResults();
	PropertyDescriptor pd = cachedIntrospectionResults.getPropertyDescriptor(propertyName);
	if (pd == null) {
		throw new InvalidPropertyException(getRootClass(), getNestedPath() + propertyName,
				"No property '" + propertyName + "' found");
	}
	TypeDescriptor td = cachedIntrospectionResults.getTypeDescriptor(pd);
	if (td == null) {
		td = cachedIntrospectionResults.addTypeDescriptor(pd, new TypeDescriptor(property(pd)));
	}
	// 执行类型转换
	return convertForProperty(propertyName, null, value, td);
}
// AbstractNestablePropertyAccessor
protected Object convertForProperty(
			String propertyName, @Nullable Object oldValue, @Nullable Object newValue, TypeDescriptor td)
			throws TypeMismatchException {

	return convertIfNecessary(propertyName, oldValue, newValue, td.getType(), td);
}
// AbstractNestablePropertyAccessoor
private Object convertIfNecessary(@Nullable String propertyName, @Nullable Object oldValue,
			@Nullable Object newValue, @Nullable Class<?> requiredType, @Nullable TypeDescriptor td)
			throws TypeMismatchException {

	Assert.state(this.typeConverterDelegate != null, "No TypeConverterDelegate");
	try {
		// 最终也会交给TypeConverterDelegate进行类型转换
		return this.typeConverterDelegate.convertIfNecessary(propertyName, oldValue, newValue, requiredType, td);
	}
	catch (ConverterNotFoundException | IllegalStateException ex) {
		PropertyChangeEvent pce =
				new PropertyChangeEvent(getRootInstance(), this.nestedPath + propertyName, oldValue, newValue);
		throw new ConversionNotSupportedException(pce, requiredType, ex);
	}
	catch (ConversionException | IllegalArgumentException ex) {
		PropertyChangeEvent pce =
				new PropertyChangeEvent(getRootInstance(), this.nestedPath + propertyName, oldValue, newValue);
		throw new TypeMismatchException(pce, requiredType, ex);
	}
}

可以看到,不管走哪个分支,最终都会交给TypeConverterDelegate进行类型转换

TypeConverterDelegate.convertIfNecessary

public <T> T convertIfNecessary(@Nullable String propertyName, @Nullable Object oldValue, @Nullable Object newValue,
			@Nullable Class<T> requiredType, @Nullable TypeDescriptor typeDescriptor) throws IllegalArgumentException {

	// Custom editor for this type?
	// 判断是否有合适的自定义editor
	PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);

	ConversionFailedException conversionAttemptEx = null;

	// No custom editor but custom ConversionService specified?
	ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
	// 如果没有合适的自定义editor,并且conversionService不为空,那么使用conversionService进行类型转换
	if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) {
		TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
		if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
			try {
				return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
			}
			catch (ConversionFailedException ex) {
				// fallback to default conversion logic below
				conversionAttemptEx = ex;
			}
		}
	}
	// 省略
}

从上面的代码可以看出TypeConverterDelegate最终调用ConversionService的convert方法来进行类型的转换
而ConversionService的convert方法又是由GenericConversionService来实现的

GenericConversionService.convert
// GenericConversionService
public Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
	Assert.notNull(targetType, "Target type to convert to cannot be null");
	// <1> 如果源类型为null,则待转换的值也必须为null
	// 这里会判断目标类型是否是Optional,如果是,则会返回Optional.empty(),否则直接返回null
	if (sourceType == null) {
		Assert.isTrue(source == null, "Source must be [null] if source type == [null]");
		return handleResult(null, targetType, convertNullSource(null, targetType));
	}
	// <2> 属性值和源类型不一致,直接抛出异常
	if (source != null && !sourceType.getObjectType().isInstance(source)) {
		throw new IllegalArgumentException("Source to convert from must be an instance of [" +
				sourceType + "]; instead it was a [" + source.getClass().getName() + "]");
	}
	// <3> 根据源类型和目标类型获取对应的GenericConverter
	GenericConverter converter = getConverter(sourceType, targetType);
	if (converter != null) {	
		// 使用GenericConverter来进行类型转换
		Object result = ConversionUtils.invokeConverter(converter, source, sourceType, targetType);
		return handleResult(sourceType, targetType, result);
	}
	return handleConverterNotFound(source, sourceType, targetType);
}
handlerResult

handlerResult的作用就是对最终转换之后的结果进行校验

// GenericConversionService
private Object handleResult(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType, @Nullable Object result) {
	// 如果结果是null,会判断目标类型是否是基础类型,如果是基础类型直接抛出异常,因为基础类型无法接收null
	if (result == null) {
		assertNotPrimitiveTargetType(sourceType, targetType);
	}
	return result;
}
convertNullSource

convertNullSource对源类型为null情况的处理,这里会根据目标类型是否是Optional,来决定返回Optional.empty还是null

protected Object convertNullSource(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
	if (targetType.getObjectType() == Optional.class) {
		return Optional.empty();
	}
	return null;
}
handleConverterNotFound

hnadlerConverterNotFound用来处理没有合适Converter的情况

// GenericConversionService
private Object handleConverterNotFound(
			@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
	// 属性值为null
	if (source == null) {
		assertNotPrimitiveTargetType(sourceType, targetType);
		return null;
	}
	//  源类型可以转换成目标类型
	if ((sourceType == null || sourceType.isAssignableTo(targetType)) &&
			targetType.getObjectType().isInstance(source)) {
		return source;
	}
	throw new ConverterNotFoundException(sourceType, targetType);
}
getConverter

getConverter的主要作用是根据源类型和目标类型来获取合适的GenericConverter

// GenericConversionService
protected GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
	// <1> 使用源类型和目标类型来生成缓存key,如果缓存中有,直接返回缓存中对应的GenericConverter
	ConverterCacheKey key = new ConverterCacheKey(sourceType, targetType);
	GenericConverter converter = this.converterCache.get(key);
	if (converter != null) {
		return (converter != NO_MATCH ? converter : null);
	}

	// <2> 如果缓存中不存在,那么会从Converters中寻找合适的GenericConverter
	converter = this.converters.find(sourceType, targetType);
	if (converter == null) {
		converter = getDefaultConverter(sourceType, targetType);
	}

	// <3> 将找到的GenericConverter放入缓存
	if (converter != null) {
		this.converterCache.put(key, converter);
		return converter;
	}

	this.converterCache.put(key, NO_MATCH);
	return null;
}
Converters

Converters用来维护所有注册进来的GenericConverter
其中有两个属性用来维护注册进来的converter

// 用来维护全局converter
private final Set<GenericConverter> globalConverters = new CopyOnWriteArraySet<>();

private final Map<ConvertiblePair, ConvertersForPair> converters = new ConcurrentHashMap<>(256);
// Converters
public GenericConverter find(TypeDescriptor sourceType, TypeDescriptor targetType) {
	// Search the full type hierarchy
	// 分别获得源类型和目标类型的类继承层次中的类
	List<Class<?>> sourceCandidates = getClassHierarchy(sourceType.getType());
	List<Class<?>> targetCandidates = getClassHierarchy(targetType.getType());
	// 分别使用源类型和目标类型类继承层次中的类来生成ConvertiblePair,在注册进来的converter中进行查找
	for (Class<?> sourceCandidate : sourceCandidates) {
		for (Class<?> targetCandidate : targetCandidates) {
			ConvertiblePair convertiblePair = new ConvertiblePair(sourceCandidate, targetCandidate);
			GenericConverter converter = getRegisteredConverter(sourceType, targetType, convertiblePair);
			if (converter != null) {
				return converter;
			}
		}
	}
	return null;
}
// Converters
private GenericConverter getRegisteredConverter(TypeDescriptor sourceType,
				TypeDescriptor targetType, ConvertiblePair convertiblePair) {

	// Check specifically registered converters
	// 分别从converters和globalConverters中进行查找
	// <1> 从converters中进行查找,首先根据源类型和目标类型,构建convertiblePair
	// 根据convertiblePair找到对应的ConvertersForPair,再从ConvertersForPair中找到合适的converter
	ConvertersForPair convertersForPair = this.converters.get(convertiblePair);
	if (convertersForPair != null) {
		GenericConverter converter = convertersForPair.getConverter(sourceType, targetType);
		if (converter != null) {
			return converter;
		}
	}
	// Check ConditionalConverters for a dynamic match
	// <2> 从全局converters中查找,则是遍历每个converter,然后调用match,判断是否可以支持当前源类型和目标类型的转换
	for (GenericConverter globalConverter : this.globalConverters) {
		if (((ConditionalConverter) globalConverter).matches(sourceType, targetType)) {
			return globalConverter;
		}
	}
	return null;
}
ConversionUtils.invokeConverter

使用找到的GenericConverter对属性进行转换

// ConversionUtils
public static Object invokeConverter(GenericConverter converter, @Nullable Object source,
			TypeDescriptor sourceType, TypeDescriptor targetType) {

	try {
		return converter.convert(source, sourceType, targetType);
	}
	catch (ConversionFailedException ex) {
		throw ex;
	}
	catch (Throwable ex) {
		throw new ConversionFailedException(sourceType, targetType, source, ex);
	}
}

Converter注册

GenericConversionService有多个重载的addConverter以及一个addConverterFactory

addConverter(Class, Class,Converter<S super S,T extends T>)

// GenericConversionService
public <S, T> void addConverter(Class<S> sourceType, Class<T> targetType, Converter<? super S, ? extends T> converter) {
	addConverter(new ConverterAdapter(
			converter, ResolvableType.forClass(sourceType), ResolvableType.forClass(targetType)));
}
public void addConverter(GenericConverter converter) {
	this.converters.add(converter);
	invalidateCache();
}

addConverter(Converter<?,?>)

public void addConverter(Converter<?, ?> converter) {
	// 获取当前converter的泛型
	ResolvableType[] typeInfo = getRequiredTypeInfo(converter.getClass(), Converter.class);
	if (typeInfo == null && converter instanceof DecoratingProxy) {
		typeInfo = getRequiredTypeInfo(((DecoratingProxy) converter).getDecoratedClass(), Converter.class);
	}
	if (typeInfo == null) {
		throw new IllegalArgumentException("Unable to determine source type <S> and target type <T> for your " +
				"Converter [" + converter.getClass().getName() + "]; does the class parameterize those types?");
	}
	addConverter(new ConverterAdapter(converter, typeInfo[0], typeInfo[1]));
}
public void addConverter(GenericConverter converter) {
	this.converters.add(converter);
	invalidateCache();
}

addConverterFactory(ConverterFactory<?,?>)

public void addConverterFactory(ConverterFactory<?, ?> factory) {
	// 获取factory的泛型
	ResolvableType[] typeInfo = getRequiredTypeInfo(factory.getClass(), ConverterFactory.class);
	if (typeInfo == null && factory instanceof DecoratingProxy) {
		typeInfo = getRequiredTypeInfo(((DecoratingProxy) factory).getDecoratedClass(), ConverterFactory.class);
	}
	if (typeInfo == null) {
		throw new IllegalArgumentException("Unable to determine source type <S> and target type <T> for your " +
				"ConverterFactory [" + factory.getClass().getName() + "]; does the class parameterize those types?");
	}
	addConverter(new ConverterFactoryAdapter(factory,
			new ConvertiblePair(typeInfo[0].toClass(), typeInfo[1].toClass())));
}
public void addConverter(GenericConverter converter) {
	this.converters.add(converter);
	invalidateCache();
}

addConverter(GenericConverter)

// GenericConversionService
public void addConverter(GenericConverter converter) {
	this.converters.add(converter);
	invalidateCache();
}

可以看到上面不同形式添加converter的方法,最终都是创建GenericConverter的实现类的实例,然后调用当前这个addConverter进行converter注册操作的,不同的是,如果入参是Converter,那么会创建ConverterAdapter;如果入参是ConverterFactory,那么会创建ConverterFactoryAdapter
接着看下Converters的add方法

// Converters
public void add(GenericConverter converter) {
	// <1> 获取当前converter的ConvertiblePair
	Set<ConvertiblePair> convertibleTypes = converter.getConvertibleTypes();
	// <2> 如果为空,加入到全局converter中
	if (convertibleTypes == null) {
		Assert.state(converter instanceof ConditionalConverter,
				"Only conditional converters may return null convertible types");
		this.globalConverters.add(converter);
	}
	else {
		// <3> 根据当前ConvertiblePair找到已有的ConvertersPair,然后将当前converter添加进去
		// 一个ConvertersForPair中包含多个GenericConverter
		for (ConvertiblePair convertiblePair : convertibleTypes) {
			getMatchableConverters(convertiblePair).add(converter);
		}
	}
}

DefaultConversionService

DefaultConversionService是GenericConversionService的默认实现类,主要的作用就是注册一些默认的converter

public static void addDefaultConverters(ConverterRegistry converterRegistry) {
	addScalarConverters(converterRegistry);
	addCollectionConverters(converterRegistry);

	converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry));
	converterRegistry.addConverter(new StringToTimeZoneConverter());
	converterRegistry.addConverter(new ZoneIdToTimeZoneConverter());
	converterRegistry.addConverter(new ZonedDateTimeToCalendarConverter());

	converterRegistry.addConverter(new ObjectToObjectConverter());
	converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry));
	converterRegistry.addConverter(new FallbackObjectToStringConverter());
	converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService) converterRegistry));
}

注册自定义Converter

spring提供了ConversionServiceFactoryBean来支持自定义Converter

// ConversionServiceFactoryBean
public class ConversionServiceFactoryBean implements FactoryBean<ConversionService>, InitializingBean {

	@Nullable
	private Set<?> converters;

	@Nullable
	private GenericConversionService conversionService;


	/**
	 * Configure the set of custom converter objects that should be added:
	 * implementing {@link org.springframework.core.convert.converter.Converter},
	 * {@link org.springframework.core.convert.converter.ConverterFactory},
	 * or {@link org.springframework.core.convert.converter.GenericConverter}.
	 */
	public void setConverters(Set<?> converters) {
		this.converters = converters;
	}

	@Override
	public void afterPropertiesSet() {
		// 创建DefaultConversionService
		this.conversionService = createConversionService();
		// 遍历convertes,将其中的每个converter注册到conversionService中
		ConversionServiceFactory.registerConverters(this.converters, this.conversionService);
	}

	/**
	 * Create the ConversionService instance returned by this factory bean.
	 * <p>Creates a simple {@link GenericConversionService} instance by default.
	 * Subclasses may override to customize the ConversionService instance that
	 * gets created.
	 */
	protected GenericConversionService createConversionService() {
		return new DefaultConversionService();
	}


	// implementing FactoryBean

	@Override
	@Nullable
	public ConversionService getObject() {
		return this.conversionService;
	}

	@Override
	public Class<? extends ConversionService> getObjectType() {
		return GenericConversionService.class;
	}

	@Override
	public boolean isSingleton() {
		return true;
	}

}

为了注册我们自己的converter,只需要在创建ConversionServiceFactoryBean的时候,通过setConverters方法将我们自己定义的converter注册进去即可

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值