类型转换系统,顾名思义,就是负责spring框架中的对象类型转换工作。
类型转换系统体系图如下:
整个类型转换系统包括两个核心接口(ConversionService和ConverterRegistry)和一个核心实现类(GenericConversionService)。
ConversionService(转换服务)接口定义了类型转换系统具有的核心功能,包括判断当前服务是否能够完成原始类型(sourceType)到目标类型(targetType)的转换,以及把原始对象(sourceObject)转换成目标类型对象。
接口如下:
2.ConverterRegistry(转换器注册表)接口,使得类型转换系统可以管理(添加或删除)内部的转换器。
所有的对象类型转换,实际都是由转换系统内部的各个转换器完成转换的。
接口如下:
转换器注册表可以管理3种类型的转换器(关于转换器,稍后详解。。。):
Converter<S,T>:把原始类型S,转换成目标类型T
GenericConverter:通用转换器
ConverterFactory<S,R>:转换器工厂,通过它可以获取Converter<S,T>对象(T extends R)。
以上两个接口都只是类型转换系统的部分功能,因此使用ConfigurableConversionService接口类整合这两部分功能。
ConfigurableConversionService接口只起整合作用,并没有定义新的功能。
GenericConversionService(通用类型转换服务),是整个类型转换系统的完整实现。它作为一个容器,可以管理转换器,同时可以调用这些转换器进行类型转换。但是,此类只是一个空的容器,内部还没有任何转换器。
DefaultConversionService(默认的类型转换服务):此类是默认的类型转换系统,它继承自GenericConversionService类,但是没有添加任何新的功能,只是在构造方法中调用addDefaultConverters向自身添加了许多默认的转换器。
部分代码如下:
public class DefaultConversionService extends GenericConversionService {
public DefaultConversionService() {
// 向当前对象中添加默认的转换器添加默认的转换器
addDefaultConverters(this);
}
public static void addDefaultConverters(ConverterRegistry converterRegistry) {
//
addScalarConverters(converterRegistry);
//
addCollectionConverters(converterRegistry);
//
converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry));
//
if (jsr310Available) {
Jsr310ConverterRegistrar.registerZoneIdConverters(converterRegistry);
}
//
converterRegistry.addConverter(new ObjectToObjectConverter());
//
converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry));
//
converterRegistry.addConverter(new FallbackObjectToStringConverter());
if (javaUtilOptionalClassAvailable) {
converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService) converterRegistry));
}
}
}
到这里,整个类型转换系统已经可以正常运行了。在基于spring框架的应用中,只需要
ConversionService conversionService = new DefaultConversionService();
即可以使用这个系统进行类型转换了。
下面来说说转换器。
从GenericConversionService类的源码中可以看到,converters保存了所有的转换器(Converters类是GenericConversionService的成员内部类)。
/**
* GenericConversionService
*/
// 当前变量保存了所有的转换器
private final Converters converters = new Converters();
且刚刚上文已经提到,共有3种类型的转换器:
Converter<S,T>:把原始类型S,转换成目标类型T
GenericConverter:通用转换器
ConverterFactory<S,R>:转换器工厂,通过它可以获取Converter<S,T>对象(T extends R)。
但是,添加到converters中的转换器都是GenericConverter类型(或者说是ConditionalGenericConverter类型)的转换器,这一点可以从所有addConverter方法观察到。
那么Converter<S,T>和ConverterFactory<S,R>与GenericConverter之间又有什么关系呢?
从GenericConversionService源码中可以看到,spring框架通过适配器模式,将Converter<S,T>接口和ConverterFactory<S,R>接口都转换成了GenericConverter类型(实际类型为ConditionalGenericConverter)。这一过程是由GenericConversionService的成员内部类ConverterAdapter完成的。
GenericConverter通用转换器体系图如下:
1.GenericConverter:通用转换器,定义了2种功能,一是获取可转换的类型组合的集合,一是根据原始类型和目标类型对原始对象进行类型转换。
关于TypeDiscriptor类型描述器,稍后解释。
接口中的成员内部类ConvertiblePair,描述了一个原始类型到目标类型的组合。
public static final class ConvertiblePair {
// 原始类型
private final Class<?> sourceType;
// 目标类型
private final Class<?> targetType;
}
2.ConditionalConverter:有条件的转换器,此接口定义了一个功能,就是判断当前转换器是否可以完成原始类型到目标类型的转换。
3.ConditionalGenericConverter:有条件的通用转换器,整合了上述的连个接口的功能。
接下来就是org.springframework.core.convert.support包中,各种转换器的实现了。一般情况下,转换器都需要实现ConditionalGenericConverter接口,只有极少数转换器只实现了GenericConverter接口。
最后,附上DefaultGenericConversionService可转换的所有ConvertiblePai列表:
格式:sourceType-->targetType
Number-->Number String-->Number Number-->String String-->Character Character-->String Number-->Character Character-->Number String-->Boolean Boolean-->String String-->Enum Enum-->String String-->Locale Locale-->String String-->Properties Properties-->String String-->UUID UUID-->String Object[]-->Collection Collection-->Object[] Object[]-->Object[] Collection-->Collection Map-->Map Object[]-->String String-->Object[] Object[]-->Object Object-->Object[] Collection-->String String-->Collection Collection-->Object Object-->Collection ByteBuffer-->Object ByteBuffer-->byte[] byte[]-->ByteBuffer Object-->ByteBuffer ZoneId-->TimeZone ZonedDateTime-->Calendar Object-->Object Object-->String Object-->Optional |