【Spring】关于Spring 的类型转换 ConversionService TypeConverter 等
前言
Spring
框架层面的转换能力,主要一部分都是由 ConversionService
提供,本章节简单聊一下 Spring
转换服务相关:
- 转换器
API
:Converter
ConverterFactory
GenericConverter
等 - 转换服务:
ConversionService
系列 Formatter
与Converter
的整合- 统一转换服务出口
TypeConverter
转换器 API
Converter
@FunctionalInterface
public interface Converter<S, T> {
@Nullable
T convert(S source);
}
- 很简单的一个函数式接口,
S
转换为T
- 示例略
ConverterFactory
public interface ConverterFactory<S, R> {
<T extends R> Converter<S, T> getConverter(Class<T> targetType);
}
- 允许
S
转换为R
子类集合,即一对多
的转换 - 可参考官方提供的实现如
NumberToNumberConverterFactory
ConditionalConverter
public interface ConditionalConverter {
boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
}
matches
基于类型判断是否匹配- 后文提到的
GenericConverter
会大量使用该接口
GenericConverter
public interface GenericConverter {
@Nullable
Set<ConvertiblePair> getConvertibleTypes();
@Nullable
Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
final class ConvertiblePair {
private final Class<?> sourceType;
private final Class<?> targetType;
// ...
}
}
- 这是最灵活最复杂的一个转换器接口,因为它支持
多对多
的转换服务 - 具体的转换类型由内部类
ConvertiblePair
维护,方法getConvertibleTypes
返回该转换器支持的转换类型集合
转换服务
ConversionService
public interface ConversionService {
boolean canConvert(@Nullable Class<?> sourceType, Class<?> targetType);
boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType);
@Nullable
<T> T convert(@Nullable Object source, Class<T> targetType);
@Nullable
Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType);
}
canConvert
,是否支持目标类型的转换convert
由转换服务(选择对应的转换器)进行转换
ConverterRegistry
public interface ConverterRegistry {
void addConverter(Converter<?, ?> converter);
<S, T> void addConverter(Class<S> sourceType, Class<T> targetType, Converter<? super S, ? extends T> converter);
void addConverter(GenericConverter converter);
void addConverterFactory(ConverterFactory<?, ?> factory);
void removeConvertible(Class<?> sourceType, Class<?> targetType);
}
XXXRegistry
,注册(管理)中心的模式- 提供对
转换器
的注册与管理
ConfigurableConversionService
public interface ConfigurableConversionService extends ConversionService, ConverterRegistry {
}
- 它的子类是一个
ConversionService
,负责选择转换器进行对应类型的转换 - 它的子类是一个
ConverterRegistry
,负责维护一组转换器
GenericConversionService
- 转换服务的所有逻辑基本在这个类实现:转换器的维护、指定类型的转换等
- 它的实现是否精巧,借助两个内部类:
Converts
维护ConvertiblePair
到ConvertersForPair
关系,即根据转换数据的类型获取转换器
集合ConvertersForPair
维护对应的转换器
集合,即获取唯一一个转换器
实例进行转换操作,这里获取的就是符合条件
(比如match
方法)的第一个转换器
- 细节过多就不展开了,感兴趣可以自己看下
DefaultConversionService
ConversionService
的默认实现- 没什么额外的逻辑,主要是默认注册了很多
转换器
,基本可以应对所有普通的转换类型
格式化与类型转换的整合
Printer
@FunctionalInterface
public interface Printer<T> {
String print(T object, Locale locale);
}
Parser
@FunctionalInterface
public interface Parser<T> {
T parse(String text, Locale locale) throws ParseException;
}
Formatter
public interface Formatter<T> extends Printer<T>, Parser<T> {
}
- 格式化,其实就可以看作一种类型转换:
String
和T
之间的转换 - 所有可以理解为一个
Formatter
对应两个转换器
FormatterRegistry
public interface FormatterRegistry extends ConverterRegistry {
void addPrinter(Printer<?> printer);
void addParser(Parser<?> parser);
void addFormatter(Formatter<?> formatter);
void addFormatterForFieldType(Class<?> fieldType, Formatter<?> formatter);
void addFormatterForFieldType(Class<?> fieldType, Printer<?> printer, Parser<?> parser);
void addFormatterForFieldAnnotation(AnnotationFormatterFactory<? extends Annotation> annotationFormatterFactory);
}
Formatter
的注册中心,它同时还是一个ConverterRegistry
,这里其实是一个组合的关系- 支持
Printer
和Parser
的单独注册以及Formatter
的注册
FormattingConversionService
public class FormattingConversionService extends GenericConversionService
implements FormatterRegistry, EmbeddedValueResolverAware {
// ...
// 对于 Printer 适配成 PrinterConverter 注册
@Override
public void addPrinter(Printer<?> printer) {
Class<?> fieldType = getFieldType(printer, Printer.class);
addConverter(new PrinterConverter(fieldType, printer, this));
}
// 对于 Parser 适配成 ParserConverter 注册
@Override
public void addParser(Parser<?> parser) {
Class<?> fieldType = getFieldType(parser, Parser.class);
addConverter(new ParserConverter(fieldType, parser, this));
}
// 一个 Formatter 对于两个 Converter
@Override
public void addFormatterForFieldType(Class<?> fieldType, Formatter<?> formatter) {
addConverter(new PrinterConverter(fieldType, formatter, this));
addConverter(new ParserConverter(fieldType, formatter, this));
}
// ...
}
- 之前提到,
Formatter
可以理解为T
到String
类型的Converter
,FormattingConversionService
就依赖这个思想实现 - 对于
Printer
和Parser
分别适配成PrinterConverter
和ParserConverter
注册,适配器设计模式
的经典场景 - 注册方法
addConverter
由父类GenericConversionService
提供,组合设计模式
的经典场景
DefaultFormattingConversionService
- 跟
DefaultConversionService
的思路一样,同时也是DefaultConversionService
的子类 - 在
DefaultConversionService
注册的转换器之上,再注册一些默认的Formatter
TypeConverter
public interface TypeConverter {
@Nullable
<T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType) throws TypeMismatchException;
@Nullable
<T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType,
@Nullable MethodParameter methodParam) throws TypeMismatchException;
@Nullable
<T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType, @Nullable Field field)
throws TypeMismatchException;
@Nullable
default <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType,
@Nullable TypeDescriptor typeDescriptor) throws TypeMismatchException {
throw new UnsupportedOperationException("TypeDescriptor resolution not supported");
}
}
- 除了
转换服务
,JDK
提供的PropertyEditor
也提供类似的机制,TypeConverter
统一上述所有转换的出口 - 子类
TypeConverterSupport
作为抽象基类,把上述方法的实现都委托给TypeConverterDelegate
TypeConverterDelegate
再往下就是基于PropertyEditor
和ConversionService
进行转换了,细节不再深入Spring
容器中的默认TypeConverter
实例为SimpleTypeConverter
总结
Spring
的数据转换在体现在方方面面:
- 单纯的类型转换,比如
BeanFactory#getBean
方法的类型转换等 - 数据绑定,比如
DataBinder
绑定数据时,必然也涉及类型的转换 - 等等