最近封装 RPC 相关的模块,领导说数据转换可以考虑使用 Spring 原有的 Converter 体系。
Converter
最简单的转换器、相关的顶层接口有ConditionalConverter
、GenericConverter
、ConverterFactory
、ConvertingComparator
、ConverterRegistry
ConversionService
Spring 数据转换的入口、它根据相关参数将调用路由到具体的 Converter。 相关的接口和类FormattingConversionService
、DefaultConversionService
、ConversionServiceFactoryBean
、FormattingConversionServiceFactoryBean
Converter
/** * A converter converts a source object of type {@code S} to a target of type {@code T}. * * <p>Implementations of this interface are thread-safe and can be shared. * * <p>Implementations may additionally implement {@link ConditionalConverter}. * * @author Keith Donald * @since 3.0 * @param <S> the source type * @param <T> the target type */ @FunctionalInterface public interface Converter<S, T> { /** * Convert the source object of type {@code S} to target type {@code T}. * @param source the source object to convert, which must be an instance of {@code S} (never {@code null}) * @return the converted object, which must be an instance of {@code T} (potentially {@code null}) * @throws IllegalArgumentException if the source cannot be converted to the desired target type */ @Nullable T convert(S source); } 复制代码
实现该接口要确保其线程安全、一般来说除了实现该接口、还会实现 ConditionalConverter
接口
看一些常见的 Spring 内部提供给我们使用的
字符串转布尔
final class StringToBooleanConverter implements Converter<String, Boolean> { private static final Set<String> trueValues = new HashSet<>(8); private static final Set<String> falseValues = new HashSet<>(8); static { trueValues.add("true"); trueValues.add("on"); trueValues.add("yes"); trueValues.add("1"); falseValues.add("false"); falseValues.add("off"); falseValues.add("no"); falseValues.add("0"); } @Override @Nullable public Boolean convert(String source) { String value = source.trim(); if (value.isEmpty()) { return null; } value = value.toLowerCase(); if (trueValues.contains(value)) { return Boolean.TRUE; } else if (falseValues.contains(value)) { return Boolean.FALSE; } else { throw new IllegalArgumentException("Invalid boolean value '" + source + "'"); } } } 复制代码
字符转 Charset
class StringToCharsetConverter implements Converter<String, Charset> { @Override public Charset convert(String source) { return Charset.forName(source); } } 复制代码
Converter 是一比一之间的转换、相对来说是比较简单的
ConverterFactory
这个是一比多之间的转换
public interface ConverterFactory<S, R> { /** * Get the converter to convert from S to target type T, where T is also an instance of R. * @param <T> the target type * @param targetType the target type to convert to * @return a converter from S to T */ <T extends R> Converter<S, T> getConverter(Class<T> targetType); } 复制代码
看下 String 转为各种枚举类
final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> { @Override public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) { return new StringToEnum(ConversionUtils.getEnumType(targetType)); } private static class StringToEnum<T extends Enum> implements Converter<String, T> { private final Class<T> enumType; public StringToEnum(Class<T> enumType) { this.enumType = enumType; } @Override @Nullable public T convert(String source) { if (source.isEmpty()) { // It's an empty enum identifier: reset the enum value to null. return null; } return (T) Enum.valueOf(this.enumType, source.trim()); } } } 复制代码
GenericConverter
N:N 的转换
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; public ConvertiblePair(Class<?> sourceType, Class<?> targetType) { this.sourceType = sourceType; this.targetType = targetType; } } } 复制代码
看一下 ObjectToOptionalConverter
final class ObjectToOptionalConverter implements ConditionalGenericConverter { private final ConversionService conversionService; public ObjectToOptionalConverter(ConversionService conversionService) { this.conversionService = conversionService; } @Override public Set<ConvertiblePair> getConvertibleTypes() { Set<ConvertiblePair> convertibleTypes = new LinkedHashSet<>(4); convertibleTypes.add(new ConvertiblePair(Collection.class, Optional.class)); convertibleTypes.add(new ConvertiblePair(Object[].class, Optional.class)); convertibleTypes.add(new ConvertiblePair(Object.class, Optional.class)); return convertibleTypes; } @Override public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { if (targetType.getResolvableType().hasGenerics()) { return this.conversionService.canConvert(sourceType, new GenericTypeDescriptor(targetType)); } else { return true; } } @Override public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { return Optional.empty(); } else if (source instanceof Optional) { return source; } else if (targetType.getResolvableType().hasGenerics()) { Object target = this.conversionService.convert(source, sourceType, new GenericTypeDescriptor(targetType)); if (target == null || (target.getClass().isArray() && Array.getLength(target) == 0) || (target instanceof Collection && ((Collection<?>) target).isEmpty())) { return Optional.empty(); } return Optional.of(target); } else { return Optional.of(source); } } @SuppressWarnings("serial") private static class GenericTypeDescriptor extends TypeDescriptor { public GenericTypeDescriptor(TypeDescriptor typeDescriptor) { super(typeDescriptor.getResolvableType().getGeneric(), null, typeDescriptor.getAnnotations()); } } } 复制代码
这里借助了 ConversionService
协助将 source 对象转换为 Optional
中 T 泛型对象
可以看到 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); } 复制代码
如果是泛型相关建议使用 TypeDescriptor
参数的 converter
方法
网络异常,图片无法展示
|
我们看一下 ConverterRegistry
网络异常,图片无法展示
|
ConfigurableConversionService
ConfigurableConversionService
只是做了两个接口的整合、啥都没做
public interface ConfigurableConversionService extends ConversionService, ConverterRegistry { } 复制代码
GenericConversionService
GenericConversionService
是 ConversionService
和 ConverterRegistry
的实现类
public class GenericConversionService implements ConfigurableConversionService { // 当不需要进行转换的时候使用该转换器、也就是源对象的类型是目标类型或者其子类 private static final GenericConverter NO_OP_CONVERTER = new NoOpConverter("NO_OP"); // 没有找到合适的转换器、使用该转换器作为占位符、放在缓存 Map 中占位 private static final GenericConverter NO_MATCH = new NoOpConverter("NO_MATCH"); // 内部类、用来管理 Converter 的 private final Converters converters = new Converters(); // 缓存、可以看到 value 是 GenericConverter private final Map<ConverterCacheKey, GenericConverter> converterCache = new ConcurrentReferenceHashMap<>(64); @Override public void addConverter(Converter<?, ?> converter) { ResolvableType[] typeInfo = getRequiredTypeInfo(converter.getClass(), Converter.class); // 转为 GenericConverter addConverter(new ConverterAdapter(converter, typeInfo[0], typeInfo[1])); } @Override public <S, T> void addConverter(Class<S> sourceType, Class<T> targetType, Converter<? super S, ? extends T> converter) { // 转为 GenericConverter addConverter(new ConverterAdapter( converter, ResolvableType.forClass(sourceType), ResolvableType.forClass(targetType))); } @Override public void addConverter(GenericConverter converter) { this.converters.add(converter); invalidateCache(); } @Override public void addConverterFactory(ConverterFactory<?, ?> factory) { // 获取声明的泛型信息 ResolvableType[] typeInfo = getRequiredTypeInfo(factory.getClass(), ConverterFactory.class); ........ // 转为 GenericConverter addConverter(new ConverterFactoryAdapter(factory, new ConvertiblePair(typeInfo[0].toClass(), typeInfo[1].toClass()))); } @Override public void removeConvertible(Class<?> sourceType, Class<?> targetType) { this.converters.remove(sourceType, targetType); invalidateCache(); } @Override public boolean canConvert(@Nullable Class<?> sourceType, Class<?> targetType) { Assert.notNull(targetType, "Target type to convert to cannot be null"); return canConvert((sourceType != null ? TypeDescriptor.valueOf(sourceType) : null), TypeDescriptor.valueOf(targetType)); } @Override public boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) { Assert.notNull(targetType, "Target type to convert to cannot be null"); if (sourceType == null) { return true; } GenericConverter converter = getConverter(sourceType, targetType); return (converter != null); } public boolean canBypassConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) { Assert.notNull(targetType, "Target type to convert to cannot be null"); if (sourceType == null) { return true; } GenericConverter converter = getConverter(sourceType, targetType); return (converter == NO_OP_CONVERTER); } @Override @SuppressWarnings("unchecked") @Nullable public <T> T convert(@Nullable Object source, Class<T> targetType) { Assert.notNull(targetType, "Target type to convert to cannot be null"); return (T) convert(source, TypeDescriptor.forObject(source), TypeDescriptor.valueOf(targetType)); } @Override @Nullable public Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType) { ....... GenericConverter converter = getConverter(sourceType, targetType); if (converter != null) { Object result = ConversionUtils.invokeConverter(converter, source, sourceType, targetType); return handleResult(sourceType, targetType, result); } return handleConverterNotFound(source, sourceType, targetType); } 复制代码