一.概述
转换系统是不同范式系统间交互常常会需要碰到的,如WEB 中HTTP KV文本流到对象的转换和对象到http KV文本流的转换;还有对象到关系型DB和关系型DB到对象之间的转换(ORM)。
一个面向对象的转换系统涉及到以下几个方面:
1. 转换映射,
如类型转换:String—>Number,Boolean—>String,String—>Boolean;
字段转换:从一个类声明的字段变成另一个类声明的字段(包括类型和值);
参数转换:从一个方法声明的参数变成另一个方法声明的参数(包括类型和内容)。
2. 转换器负责具体的转换操作。
3. 转换映射和转换器的对应关系。(多对多的关系)
二.Spring的解决方案
1. 转换映射:
采用泛型来对类型映射进行参数化。类型转换是在两种类型中进行的,一种是原始类型,一种是目标类型,将这个泛型化。S—>T,—>extends T
采用TypeDescriptor对参数和字段进行描述,达到扩大转换语境(从类型信息到字段信息)的效果。
2. 转换器
一对一的映射可以用Convert<S,T>来表示,
一对多且多方类型具有继承体系可以用ConverterFactory<S,R>, R 是所有目标类型的基类,可以从工厂中得到对应的Converter<S,T extends R>
更为强大的是GenericConverter 可以将转换从类型之间扩展到字段、参数之间,也就是可以根据声明类型的字段、参数的配置来改变转换逻辑,比如数组到集合的转变,可以读到原始声明元素类型和目标声明元素类型来做动态映射。
3. 转换映射器:在GenericConversionService 有存储字段
private final Map<Class<?>, Map<Class<?>, MatchableConverters>> converters =new HashMap<Class<?>, Map<Class<?>, MatchableConverters>>(36);
这个Map描述了原始类型到目标类型的映射。
4.SRP
ConversionService 只提供转换方法,ConverterRegistry中提供Converter的增加,修改,去除,将两者功能分离在不同的接口中。GenereicConversionService 提供了转换接口的默认实现,并支持CovnertFactory,Coverter和GenericConverter的注册。
三、 web 中涉及的KV 到对象和对象到KV的转换:
web客户端是以kv结构来传递数据到web服务端,涉及的问题有两个:
1. 如何从平面性的kv结构变成树形的对象属性结构
2. 如何从字符串转换成相应的对象中的类型。
第一个问题可以命名一套规范来标识对象中的一个属性,
比如
public Class User{
private UserName name;
}
Class UserName{
private String firstName;
private String lastName;
}
那么如何用kv系统来表示firstName的值是多少呢?可以发明一套标识系统,如name.firstName,用.来表示嵌套关系。
至于类型转换,则可以考虑从类声明定义来查找,从而从String转成声明的类型。