Spring通用类型转换的实现原理
- 设计思路
- 实现逻辑
- ConversionService:类型转换服务入口
- ConverterRegister:转换器注册接口
- GenericConversionService
- 1. `Map<ConvertiblePair, GenericConverter> converters`
- 2. `canConvert()` 与 `convert()`:服务入口
- 3. `getConverter()`:匹配最合适的转换器
- 4. `addConverter()` 和 `addConverterFactory()`
- 5. `getRequiredTypeInfo()`
- 6. 完整代码
源码见:mini-spring
设计思路
在前面我们聊了Spring类型转换的三种实现方式,但现在也遇到一个问题,在后续我们将类型转换融入Spring生命周期的时候对于这三种方式如何选择,如何管理。就从这个角度来看的话,是不是还不如只定义一种方式。
对于这个问题Spring也给出了解决方案:
在类型转换系统中保留一个核心注册接口 + 多种适配实现,是 Spring 推荐的设计;但对于业务开发者或自定义扩展场景,通常只需选择一种实现方式(推荐 Converter<S, T>
)并注册到统一的转换服务中即可。真正集成到 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。
实现逻辑
ConversionService:类型转换服务入口
public interface ConversionService { /** * 检查是否可以将源类型转换为目标类型 * * @param sourceType 源类型的Class对象 * @param targetType 目标类型的Class对象 * @return 如果可以进行转换则返回true,否则返回false */ boolean canConvert(Class<?> sourceType, Class<?> targetType); /** * 将给定的源对象转换为目标类型 * * @param source 要转换的源对象 * @param targetType 目标类型的Class对象 * @param <T> 目标类型的泛型参数 * @return 转换后的目标类型对象 */ <T> T convert(Object source, Class<T> targetType);
}
-
判断是否支持某种类型对的转换
-
提供统一的类型转换执行入口
ConverterRegister:转换器注册接口
public interface ConverterRegister { void addConverter(Converter<?, ?> converter); void addConverter(GenericConverter genericConverter); void addConverterFactory(ConverterFactory converterFactory);
}
-
三种类型转换器的注册入口
-
最终都会适配为
GenericConverter
存储
GenericConversionService
Spring 支持三种转换器接口(Converter
、ConverterFactory
、GenericConverter
),但使用上不应让开发者关心这些差异。
目的:
-
将三种接口适配为统一的
GenericConverter
类型 -
统一注册到一个容器(这里是
Map<ConvertiblePair, GenericConverter>
) -
提供
canConvert()
和convert()
方法对外暴露转换能力
1. Map<ConvertiblePair, GenericConverter> converters
- 核心转换器容器:key 是 “源类型 → 目标类型” 的类型对,value 是对应的转换器。
Map<ConvertiblePair, GenericConverter> converters = new HashMap<>();
2. canConvert()
与 convert()
:服务入口
@Override
public boolean canConvert(Class<?> sourceType, Class<?> targetType)
判断是否存在某种类型转换器(从 sourceType → targetType
)
@Override
public <T> T convert(Object source, Class<T> targetType)
实际执行转换,内部通过 getConverter()
获取匹配的 GenericConverter
3. getConverter()
:匹配最合适的转换器
protected GenericConverter getConverter(Class<?> sourceType, Class<?> targetType)
核心逻辑:
-
递归获取 source 和 target 的继承结构(
getClassHierarchy()
) -
生成
ConvertiblePair
对象 -
在
converters
中查找是否存在该对的转换器
支持子类转父类、接口匹配等灵活匹配机制
4. addConverter()
和 addConverterFactory()
public void addConverter(Converter<?, ?> converter)
-
将实现了
Converter<S, T>
的对象适配为GenericConverter
(通过ConverterAdapter
) -
注册到
converters
容器中
public void addConverterFactory(ConverterFactory<?, ?> converterFactory)
- 同理,适配
ConverterFactory
为GenericConverter
(通过ConverterFactoryAdapter
)
5. getRequiredTypeInfo()
private ConvertiblePair getRequiredTypeInfo(Object object)
这个方法利用 反射 + 泛型解析:
-
读取类所实现的接口的泛型参数类型
-
自动识别该转换器是支持
S → T
哪两个类型
举例:
class StringToIntegerConverter implements Converter<String, Integer>
会被解析为:
ConvertiblePair(String.class, Integer.class)
6. 完整代码
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); } }
}