image.png

Spring 3.0 提供了三种类型的转换器(ConverterConverterFactoryGenericConverter),分别用来处理 1:1、1:N、N:N 的类型转换。ConversionService类统一管理所有的类型转换器,负责注册、查找、转换等功能,统一对外提供服务。

Example

DefaultConversionService

DefaultConversionServiceGenericConverter子类,示例demo:

  1. String转成Boolean:

    1. @Test
    2. public void testConverter() {
    3. DefaultConversionService serivce = new DefaultConversionService();
    4. // 类型能否转换
    5. boolean actual = serivce.canConvert(String.class, Boolean.class);
    6. Assert.assertEquals(true, actual);
    7. // 类型转换结果
    8. Object acc = serivce.convert("true", Boolean.class);
    9. Assert.assertEquals(true, ((Boolean)acc).booleanValue());
    10. }
  2. String转成List:

    1. public static void main(String[] args) {
    2. DefaultConversionService serivce = new DefaultConversionService();
    3. List convert = serivce.convert("a,b,c,d", List.class);
    4. System.out.println(convert); // [a, b, c, d]
    5. }

    Converter

    是一个函数接口@FunctionalInterface public interface Converter<S, T> {...}

  3. Object转String:

    1. // ObjectToStringConverter
    2. final class ObjectToStringConverter implements Converter<Object, String> {
    3. @Override
    4. public String convert(Object source) {
    5. return source.toString();
    6. }
    7. }
  4. 自定义数据转换器

    1. // 把形如这样的字符串: "fsx:18" 转换为Person对象
    2. public class PersonConverter implements Converter<String, Person> {
    3. @Override
    4. public Person convert(String source) {
    5. if (StringUtils.isEmpty(source)) {
    6. return null;
    7. }
    8. String[] strings = StringUtils.delimitedListToStringArray(source, ":");
    9. Person person = new Person();
    10. person.setName(strings[0]);
    11. person.setAge(Integer.valueOf(strings[1]));
    12. return person;
    13. }
    14. public static void main(String[] args) {
    15. PersonConverter personConverter = new PersonConverter();
    16. System.out.println(personConverter.convert("fsx:18")); //Person{name='fsx', age=18}
    17. }
    18. }

ConverterFactory

可以将对象从S转换为R的子类型(1:N),该工厂就是用来创建一个converter,把目标类型转换成子类型,所以它是1->N的。注意:Spring内置的实现也都是外部不可访问的

  1. public interface ConverterFactory<S, R> {
  2. /**
  3. * Get the converter to convert from S to target type T, where T is also an instance of R.
  4. * @param <T> the target type
  5. * @param targetType the target type to convert to
  6. * @return a converter from S to T
  7. */
  8. <T extends R> Converter<S, T> getConverter(Class<T> targetType);
  9. }

demo:

  1. final class IntegerToEnumConverterFactory implements ConverterFactory<Integer, Enum> {
  2. // ConversionUtils.getEnumType表示拿出枚举的class类型
  3. @Override
  4. public <T extends Enum> Converter<Integer, T> getConverter(Class<T> targetType) {
  5. return new IntegerToEnum(ConversionUtils.getEnumType(targetType));
  6. }
  7. // 内部类的实现 把Integer转为Enum的子类型~~~ 相当于根据integer找到一个enum(注意此处根据角标来找的)
  8. private class IntegerToEnum<T extends Enum> implements Converter<Integer, T> {
  9. private final Class<T> enumType;
  10. public IntegerToEnum(Class<T> enumType) {
  11. this.enumType = enumType;
  12. }
  13. @Override
  14. public T convert(Integer source) {
  15. return this.enumType.getEnumConstants()[source];
  16. }
  17. }
  18. }
  19. // StringToEnumConverterFactory 大体同上 return (T) Enum.valueOf(this.enumType, source.trim())
  20. ...

GenericConverter

用于在两个或多个类型之间转换的通用转换器接口。这是最灵活的转换器SPI接口,也是最复杂的。灵活是因为它一个转换器就能转换多个s/t,所以它是N->N的。实现类们一般情况下也会实现接口:ConditionalConverter

它的实现类都是子接口ConditionalGenericConverter的实现类(就是GenericConverter和ConditionalConverter的结合)

参考

【1】:https://cloud.tencent.com/developer/article/1497687