Spring ConversionService 类型转换(一)Converter
Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html)
Spring ConversionService 类型转换系列文章:
- Spring ConversionService 类型转换(一)Converter
- Spring ConversionService 类型转换(二)ConversionService
JDK 提供的 PropertyEditor 只能将 String 类型转为 Object,如果要将一种 Object 类型转换成另一种 Object 类型就只能使用 Spring 提供的 ConversionService 了,这些类都位于 org.springframework.core.convert 包下。
一、ConversionService 使用
private ConversionService conversionService;
@Before
public void before() {
conversionService = new DefaultConversionService();
}
@Test
public void test() {
ConversionService conversionService = new DefaultConversionService();
Integer value = conversionService.convert("1", Integer.class);
Assert.assertTrue(value == 1);
}
在 DefaultConversionService 组件中已经注册了 Spring 默认的觉转换器,可以分为以下几类:
Converter
一对一转换,把 S 类型转化成 T 类型,最常用的转换器ConverterFactory
一对 N 转换GenericConverter
N 对 N 转换
二、三种转换器
2.1 Converter(1:1)
(1) 接口
@FunctionalInterface
public interface Converter {
T convert(S source);
}
Converter接口很简单,就是把 S 类型转化成 T 类型。我们看一下使用方法:
(2) 测试
@Test
public void converterTest() {
// ObjectToStringConverter
Assert.assertEquals("false", conversionService.convert(false, String.class));
// StringToBooleanConverter
Assert.assertTrue(conversionService.convert("true", Boolean.class));
}
(3) ObjectToStringConverter 分析
ObjectToStringConverter 和 StringToBooleanConverter 都是在 DefaultConversionService 中内置的。
final class ObjectToStringConverter implements Converter
2.2 ConverterFactory(1:N)
(1) 接口
public interface ConverterFactory {
Converter getConverter(Class targetType);
}
R 的子类都可以统一由这个 ConverterFactory 进行转换。
(2) 测试
// 测试 ConverterFactory StringToNumberConverterFactory
@Test
public void converterFactoryTest() {
Assert.assertTrue(conversionService.convert("1.2", double.class) == 1.2d);
Assert.assertTrue(conversionService.convert("1", int.class) == 1);
Assert.assertTrue(conversionService.convert("0x10", byte.class) == 0x10);
}
这里用到了 StringToNumberConverterFactory 把 String 转化成了 Number 的各个子类型,代码其实很简单:
(3) StringToNumberConverterFactory 分析
final class StringToNumberConverterFactory implements ConverterFactory {
@Override
public Converter getConverter(Class targetType) {
return new StringToNumber<>(targetType);
}
private static final class StringToNumber implements Converter {
private final Class targetType;
public StringToNumber(Class targetType) {
this.targetType = targetType;
}
@Override
public T convert(String source) {
if (source.isEmpty()) {
return null;
}
// String 类型转换成 Number
return NumberUtils.parseNumber(source, this.targetType);
}
}
}
2.3 GenericConverter(N:N)
(1) 接口
public interface GenericConverter {
// 可以转换的类型
Set getConvertibleTypes();
Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
final class ConvertiblePair {
private final Class> sourceType;
private final Class> targetType;
}
}
// 匹配 GenericConverter
public interface ConditionalConverter {
boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
}
public interface ConditionalGenericConverter extends GenericConverter, ConditionalConverter {
}
GenericConverter 是 N:N 的转化,支持转化的所有类型都写在了属性 Set 内。
(2) 测试
// 测试 GenericConverter CollectionToCollectionConverter
@Test
public void genericConverterTest() {
List list = Arrays.asList(1, 2, 3, 4, 5);
Set set = (Set) conversionService.convert(list,
TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(Integer.class)),
TypeDescriptor.collection(Set.class, TypeDescriptor.valueOf(String.class)));
// List -> Set
Assert.assertEquals("1", set.toArray(new String[0])[0]);
}
这里用到了 CollectionToCollectionConverter
(3) CollectionToCollectionConverter 分析
final class CollectionToCollectionConverter implements ConditionalGenericConverter {
private final ConversionService conversionService;
public CollectionToCollectionConverter(ConversionService conversionService) {
this.conversionService = conversionService;
}
@Override
public Set getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Collection.class, Collection.class));
}
@Override
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
return ConversionUtils.canConvertElements(
sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor(), this.conversionService);
}
@Override
public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (source == null) {
return null;
}
Collection> sourceCollection = (Collection>) source;
// 集合类型
boolean copyRequired = !targetType.getType().isInstance(source);
// 1. targetType 集合类型没变,不用转换
if (!copyRequired && sourceCollection.isEmpty()) {
return source;
}
// 集合元素类型
TypeDescriptor elementDesc = targetType.getElementTypeDescriptor();
// 2. targetType 集合元素没有指定类型,即 Object,且集合类型没变
if (elementDesc == null && !copyRequired) {
return source;
}
// 创建一个空集合
Collection
参考:
- 《Spring 学习记录 3 ConversionService》:https://www.cnblogs.com/abcwt112/p/7447435.html
每天用心记录一点点。内容也许不重要,但习惯很重要!