4. 上新了Spring,全新一代类型转换机制(中)

简介: 4. 上新了Spring,全新一代类型转换机制(中)

ConverterFactory


从名称上看它代表一个转换工厂:可以将对象S转换为R的所有子类型,从而形成1:N的关系。


该接口描述为xxxFactory是非常合适的,很好的表达了1:N的关系


public interface ConverterFactory<S, R> {
  <T extends R> Converter<S, T> getConverter(Class<T> targetType);
}


它同样也是个函数式接口。该接口的实现类并不多,Spring Framework共提供了5个内建实现(访问权限全部为default):


image.png


以StringToNumberConverterFactory为例看看实现的套路:


final class StringToNumberConverterFactory implements ConverterFactory<String, Number> {
  @Override
  public <T extends Number> Converter<String, T> getConverter(Class<T> targetType) {
    return new StringToNumber<T>(targetType);
  }
  // 私有内部类:实现Converter接口。用泛型边界约束一类类型
  private static final class StringToNumber<T extends Number> implements Converter<String, T> {
    private final Class<T> targetType;
    public StringToNumber(Class<T> targetType) {
      this.targetType = targetType;
    }
    @Override
    public T convert(String source) {
      if (source.isEmpty()) {
        return null;
      }
      return NumberUtils.parseNumber(source, this.targetType);
    }
  }
}


由点知面,ConverterFactory作为Converter的工厂,对Converter进行包装,从而达到屏蔽内部实现的目的,对使用者友好,这不正是工厂模式的优点么,符合xxxFactory的语义。但你需要清除的是,工厂内部实现其实也是通过众多if else之类的去完成的,本质上并无差异。


代码示例


/**
 * ConverterFactory:1:N
 */
@Test
public void test2() {
    System.out.println("----------------StringToNumberConverterFactory---------------");
    ConverterFactory<String, Number> converterFactory = new StringToNumberConverterFactory();
    // 注意:这里不能写基本数据类型。如int.class将抛错
    System.out.println(converterFactory.getConverter(Integer.class).convert("1").getClass());
    System.out.println(converterFactory.getConverter(Double.class).convert("1.1").getClass());
    System.out.println(converterFactory.getConverter(Byte.class).convert("0x11").getClass());
}


运行程序,正常输出:


----------------StringToNumberConverterFactory---------------
class java.lang.Integer
class java.lang.Double
class java.lang.Byte


关注点:数字类型的字符串,是可以被转换为任意Java中的数字类型的,String(1) -> Number(N)。这便就是ConverterFactory的功劳,它能处理这一类转换问题。


不足


既然有了1:1、1:N,自然就有N:N。比如集合转换、数组转换、Map到Map的转换等等,这些N:N的场景,就需要借助下一个接口GenericConverter来实现。


GenericConverter


它是一个通用的转换接口,用于在两个或多个类型之间进行转换。相较于前两个,这是最灵活的SPI转换器接口,但也是最复杂的。


public interface GenericConverter {
  Set<ConvertiblePair> getConvertibleTypes();
  Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
  // 普通POJO
  final class ConvertiblePair {
    private final Class<?> sourceType;
    private final Class<?> targetType;
  }
}


该接口并非函数式接口,虽然方法不多但稍显复杂。现对出现的几个类型做简单介绍:


  • ConvertiblePair:维护sourceType和targetType的POJO
  • getConvertibleTypes()方法返回此Pair的Set集合。由此也能看出该转换器是可以支持N:N的(大多数情况下只写一对值而已,也有写多对的)
  • TypeDescriptor:类型描述。该类专用于Spring的类型转换场景,用于描述from or to的类型
  • 比单独的Type类型强大,内部借助了ResolvableType来解决泛型议题


GenericConverter的内置实现也比较多,部分截图如下:


image.png


ConditionalGenericConverter是GenericConverter和条件接口ConditionalConverter的组合,作用是在执行GenericConverter转换时增加一个前置条件判断方法。


image.png


说明:分割线下面的4个转换器比较特殊,字面上不好理解其实际作用,比较“高级”。它们如果能被运用在日常工作中可以事半功弎,因此放在在下篇文章专门给你介绍



相关文章
|
4月前
|
存储 安全 Java
事件的力量:探索Spring框架中的事件处理机制
事件的力量:探索Spring框架中的事件处理机制
59 0
|
4月前
|
设计模式 前端开发 Java
【深入浅出Spring原理及实战】「夯实基础系列」360全方位渗透和探究SpringMVC的核心原理和运作机制(总体框架原理篇)
【深入浅出Spring原理及实战】「夯实基础系列」360全方位渗透和探究SpringMVC的核心原理和运作机制(总体框架原理篇)
62 0
|
4月前
|
Java 开发者 UED
Spring Boot的全局异常处理机制
【2月更文挑战第13天】
307 0
|
4月前
|
人工智能 JSON 前端开发
【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型)
【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型)
|
1月前
|
Java 开发工具 Spring
Spring的Factories机制介绍
Spring的Factories机制介绍
25 1
|
4月前
|
Java 测试技术 开发者
Spring IoC容器通过依赖注入机制实现控制反转
【4月更文挑战第30天】Spring IoC容器通过依赖注入机制实现控制反转
50 0
|
2月前
|
安全 Java API
构建基于Spring Boot的REST API安全机制
构建基于Spring Boot的REST API安全机制
|
3月前
|
Java 应用服务中间件 Spring
解析Spring Boot自动装配的原理与机制
解析Spring Boot自动装配的原理与机制
66 4
|
2月前
|
Java Spring
解析Spring Boot中的事务管理机制
解析Spring Boot中的事务管理机制
|
2月前
|
缓存 安全 Java
Spring Boot中的自动配置机制详解
Spring Boot中的自动配置机制详解