TypeConverterDelegate
再回到我们上面的 TypeConverterSupport 提及到的 TypeConverterDelegate
class TypeConverterDelegate { private final PropertyEditorRegistrySupport propertyEditorRegistry; @Nullable private final Object targetObject; public <T> T convertIfNecessary(@Nullable String propertyName, @Nullable Object oldValue, @Nullable Object newValue, @Nullable Class<T> requiredType, @Nullable TypeDescriptor typeDescriptor) throws IllegalArgumentException { // 查看是否为当前这个类型配置了定制的PropertyEditor PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName); ConversionFailedException conversionAttemptEx = null; // 获取当前容器中的类型转换业务类 ConversionService conversionService = this.propertyEditorRegistry.getConversionService(); // 在这里可以看出,Spring底层在进行类型转换时有两套机制 // 1.首选的是采用PropertyEditor // 2.在没有配置PropertyEditor的情况下,会采用conversionService if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) { TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue); if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) { try { // 通过conversionService进行类型转换 return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor); } catch (ConversionFailedException ex) { // fallback to default conversion logic below conversionAttemptEx = ex; } } } Object convertedValue = newValue; // 配置了定制的属性编辑器,采用PropertyEditor进行属性转换 if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) { if (typeDescriptor != null && requiredType != null && Collection.class.isAssignableFrom(requiredType) && convertedValue instanceof String) { TypeDescriptor elementTypeDesc = typeDescriptor.getElementTypeDescriptor(); if (elementTypeDesc != null) { Class<?> elementType = elementTypeDesc.getType(); if (Class.class == elementType || Enum.class.isAssignableFrom(elementType)) { convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue); } } } if (editor == null) { // 没有配置定制的属性编辑器,采用默认的属性编辑器 editor = findDefaultEditor(requiredType); } // 采用属性编辑器进行转换,需要注意的是,默认情况下PropertyEditor只会对String类型的值进行类型转换 convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor); } // ..... return (T) convertedValue; } } 复制代码
从上面的代码中我们可以知道,Spring 在实现类型转换时,有两套机制,第一套机制依赖于 PropertyEditor ,第二套机制依赖于 ConversionService 。关于属性编辑器 PropertyEditor 我们之前已经介绍过了,主要进行的是 String 到 Object 的转换,正因为如此,属性编辑器进行类型转换有很大的局限性,所以 Spring 又推出了一套 ConversionService 的体系。
ConversionService
Converter
@FunctionalInterface public interface Converter<S, T> { // 从 S 转换到 T @Nullable T convert(S source); } 复制代码
网络异常,图片无法展示
|
Spring 提供的从 S 类型转换到 T 类型的转换器
ConverterFactory
为了方便能够将 S 转为一系列的 T 类型。比如说 String 转为各种 Enum 或者 Number
网络异常,图片无法展示
|
ConverterRegistry
转换器的注册器
ConversionService
相当于 Registrar 的功能。线程安全的、其实可以从 Converter 的定义可以看出、Converter 是无状态的而不像 PropertyEditor
ApplicationConversionService
在 SpringApplication 的 run 方法的 prepareEnvironment 的 configureEnvironment 中创建了 ApplicationConversionService 并且添加了各种常见的转换器。
网络异常,图片无法展示
|
网络异常,图片无法展示
|
最后
其实这篇文章只是单纯的去了解关于 PropertyEditor 和 ConversionServer 的知识、并没有从源码详细说 Spring 怎么怎么去使用它们、这个可能放到以后的文章。这篇文章单纯是补全这个主题的基础知识、为后面继续看 Spring 的代码进行铺垫。