源码见:mini-spring
在前面我们聊了Spring类型转换的三种实现方式,但现在也遇到一个问题,在后续我们将类型转换融入Spring生命周期的时候对于这三种方式如何选择,如何管理。就从这个角度来看的话,是不是还不如只定义一种方式。
对于这个问题Spring也给出了解决方案:
在类型转换系统中保留一个核心注册接口 + 多种适配实现,是 Spring 推荐的设计;但对于业务开发者或自定义扩展场景,通常只需选择一种实现方式(推荐 Converter
)并注册到统一的转换服务中即可。真正集成到 Spring 生命周期中,核心是统一注册到 ConversionService
中。
可以用以下任意方式注册:
GenericConversionService conversionService = new GenericConversionService();
conversionService.addConverter(new StringToIntegerConverter());
Integer integer = conversionService.convert("10", Integer.class);
Assert.assertEquals(Integer.valueOf(10),integer);
conversionService.addConverterFactory(new StringToNumberConverterFactory());
Long aLong = conversionService.convert("10", Long.class);
Assert.assertEquals(Long.valueOf(10),aLong);
统一管理入口:通过 ConversionService
统一进行类型转换调用 ,简单来说就是通过适配器模式将Converter与ConverterFactory封装为GenericConverter。
public interface ConversionService {
/**
* 检查是否可以将源类型转换为目标类型
*
* @param sourceType 源类型的Class对象
* @param targetType 目标类型的Class对象
* @return 如果可以进行转换则返回true,否则返回false
*/ boolean canConvert(Class<?> sourceType, Class<?> targetType);
/**
* 将给定的源对象转换为目标类型
*
* @param source 要转换的源对象
* @param targetType 目标类型的Class对象
* @param 目标类型的泛型参数
* @return 转换后的目标类型对象
*/
<T> T convert(Object source, Class<T> targetType);
}
判断是否支持某种类型对的转换
提供统一的类型转换执行入口
public interface ConverterRegister {
void addConverter(Converter<?, ?> converter);
void addConverter(GenericConverter genericConverter);
void addConverterFactory(ConverterFactory converterFactory);
}
三种类型转换器的注册入口
最终都会适配为 GenericConverter
存储
Spring 支持三种转换器接口(Converter
、ConverterFactory
、GenericConverter
),但使用上不应让开发者关心这些差异。
目的:
将三种接口适配为统一的 GenericConverter
类型
统一注册到一个容器(这里是 Map
)
提供 canConvert()
和 convert()
方法对外暴露转换能力
Map converters
Map<ConvertiblePair, GenericConverter> converters = new HashMap<>();
canConvert()
与 convert()
:服务入口@Override
public boolean canConvert(Class<?> sourceType, Class<?> targetType)
判断是否存在某种类型转换器(从 sourceType → targetType
)
@Override
public <T> T convert(Object source, Class<T> targetType)
实际执行转换,内部通过 getConverter()
获取匹配的 GenericConverter
getConverter()
:匹配最合适的转换器protected GenericConverter getConverter(Class<?> sourceType, Class<?> targetType)
核心逻辑:
递归获取 source 和 target 的继承结构(getClassHierarchy()
)
生成 ConvertiblePair
对象
在 converters
中查找是否存在该对的转换器
支持子类转父类、接口匹配等灵活匹配机制
addConverter()
和 addConverterFactory()
public void addConverter(Converter<?, ?> converter)
将实现了 Converter
的对象适配为 GenericConverter
(通过 ConverterAdapter
)
注册到 converters
容器中
public void addConverterFactory(ConverterFactory<?, ?> converterFactory)
ConverterFactory
为 GenericConverter
(通过 ConverterFactoryAdapter
)getRequiredTypeInfo()
private ConvertiblePair getRequiredTypeInfo(Object object)
这个方法利用 反射 + 泛型解析:
读取类所实现的接口的泛型参数类型
自动识别该转换器是支持 S → T
哪两个类型
举例:
class StringToIntegerConverter implements Converter<String, Integer>
会被解析为:
ConvertiblePair(String.class, Integer.class)
public class GenericConversionService implements ConversionService, ConverterRegister {
// 用于存储通用转换器
private Map<ConvertiblePair,GenericConverter> converters = new HashMap();
/**
* 检查是否可以将源类型转换为目标类型
*
* @param sourceType 源类型的Class对象
* @param targetType 目标类型的Class对象
* @return 如果可以进行转换则返回true,否则返回false
*/ @Override
public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
GenericConverter converter = getConverter(sourceType, targetType);
return converter != null;
}
/**
* 将给定的源对象转换为目标类型
*
* @param source 要转换的源对象
* @param targetType 目标类型的Class对象
* @return 转换后的目标类型对象
*/
@Override
public <T> T convert(Object source, Class<T> targetType) {
Class<?> sourceType = source.getClass();
GenericConverter converter = getConverter(sourceType, targetType);
return (T) converter.convert(source, sourceType, targetType);
}
/**
* 获取通用适配器
* @param sourceType
* @param targetType * @return */ protected GenericConverter getConverter(Class<?> sourceType, Class<?> targetType){
List<Class<?>> sourceHierarchy = getClassHierarchy(sourceType);
List<Class<?>> targetHierarchy = getClassHierarchy(targetType);
for (Class<?> sourceCandidate : sourceHierarchy) {
for (Class<?> targetCandidate : targetHierarchy) {
ConvertiblePair convertiblePair = new ConvertiblePair(sourceCandidate, targetCandidate);
GenericConverter genericConverter = converters.get(convertiblePair);
if (genericConverter != null){
return genericConverter;
}
}
}
return null;
}
// 获取目标类的完整继承层级结构,以便于通过ConvertiblePair判断转换器是否已注册
protected List<Class<?>> getClassHierarchy(Class<?> clazz){
List<Class<?>> hierarchy = new ArrayList<>();
while ((clazz != null)){
hierarchy.add(clazz);
clazz = clazz.getSuperclass();
}
return hierarchy;
}
@Override
public void addConverter(Converter<?, ?> converter) {
// 这里传入的是一个Converter转换器对象,我们需要将其转化为GenericConverter对象
ConvertiblePair requiredTypeInfo = getRequiredTypeInfo(converter);
ConverterAdapter converterAdapter = new ConverterAdapter(converter, requiredTypeInfo);
for (ConvertiblePair convertibleType : converterAdapter.getConvertibleTypes()) {
converters.put(convertibleType,converterAdapter);
}
}
@Override
public void addConverterFactory(ConverterFactory converterFactory) {
ConvertiblePair requiredTypeInfo = getRequiredTypeInfo(converterFactory);
ConverterFactoryAdapter converterFactoryAdapter = new ConverterFactoryAdapter(converterFactory, requiredTypeInfo);
for (ConvertiblePair convertibleType : converterFactoryAdapter.getConvertibleTypes()) {
converters.put(convertibleType,converterFactoryAdapter);
}
}
/**
* 获取到目标类所实现的泛型接口的元素
* @param object
* @return */ private ConvertiblePair getRequiredTypeInfo(Object object){
Type[] types = object.getClass().getGenericInterfaces();
ParameterizedType parameterized = (ParameterizedType) types[0];
Type[] actualTypeArguments = parameterized.getActualTypeArguments();
Class sourceType = (Class) actualTypeArguments[0];
Class targetType = (Class) actualTypeArguments[1];
return new ConvertiblePair(sourceType, targetType);
}
// 通过适配器模式对Converter以及ConverterFactory进行适配
private final class ConverterAdapter implements GenericConverter{
private final Converter converter;
private final ConvertiblePair convertiblePair;
private ConverterAdapter(Converter converter, ConvertiblePair convertiblePair) {
this.converter = converter;
this.convertiblePair = convertiblePair;
}
@Override
public Object convert(Object source, Class sourceType, Class targetType) {
return converter.convert(source);
}
@Override
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(convertiblePair);
}
}
private final class ConverterFactoryAdapter implements GenericConverter{
private final ConverterFactory converterFactory;
private final ConvertiblePair convertiblePair;
private ConverterFactoryAdapter(ConverterFactory converterFactory, ConvertiblePair convertiblePair) {
this.converterFactory = converterFactory;
this.convertiblePair = convertiblePair;
}
@Override
public Object convert(Object source, Class sourceType, Class targetType) {
return converterFactory.getConverter(targetType).convert(source);
}
@Override
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(convertiblePair);
}
}
}