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

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

✍前言


你好,我是YourBatman。


上篇文章 介绍完了Spring类型转换早期使用的PropertyEditor详细介绍,关于PropertyEditor现存的资料其实还蛮少的,希望这几篇文章能弥补这块空白,贡献一份微薄之力。


如果你也吐槽过PropertyEditor不好用,那么本文将对会有帮助。Spring自3.0版本开始自建了一套全新类型转换接口,这就是本文的主要内容,接下来逐步展开。


说明:Spring自3.0后笑傲群雄,进入大一统。Java从此步入Spring的时代


版本约定


  • Spring Framework:5.3.1
  • Spring Boot:2.4.0

image.png



✍正文


在了解新一代的转换接口之前,先思考一个问题:Spring为何要自己造一套轮子呢? 一向秉承不重复造轮子原则的Spring,不是迫不得已的话是不会去动他人奶酪的,毕竟互利共生才能长久。类型转换,作为Spring框架的基石,扮演着异常重要的角色,因此对其可扩展性、可维护性、高效性均有很高要求。


基于此,我们先来了解下PropertyEditor设计上到底有哪些缺陷/不足(不能满足现代化需求),让Spring“被迫”走上了自建道路。


PropertyEditor设计缺陷


前提说明:本文指出它的设计缺陷,只讨论把它当做类型转换器在转换场景下存在的一些缺陷。


  1. 职责不单一:该接口有非常多的方法,但只用到2个而已
  2. 类型不安全:setValue()方法入参是Object,getValue()返回值是Object,依赖于约定好的类型强转,不安全
  3. 线程不安全:依赖于setValue()后getValue(),实例是线程不安全的
  4. 语义不清晰:从语义上根本不能知道它是用于类型转换的组件
  5. 只能用于String类型:它只能进行String <-> 其它类型的转换,而非更灵活的Object <-> Object


PropertyEditor存在这五宗“罪”,让Spring决定自己设计一套全新API用于专门服务于类型转换,这就是本文标题所述:新一代类型转换Converter、ConverterFactory、GenericConverter。


关于PropertyEditor在Spring中的详情介绍,请参见文章:3. 搞定收工,PropertyEditor就到这


新一代类型转换


为了解决PropertyEditor作为类型转换方式的设计缺陷,Spring 3.0版本重新设计了一套类型转换接口,有3个核心接口:


  1. Converter<S, T>:Source -> Target类型转换接口,适用于1:1转换
  2. ConverterFactory<S, R>:Source -> R类型转换接口,适用于1:N转换
  3. GenericConverter:更为通用的类型转换接口,适用于N:N转换

   1.注意:就它没有泛型约束,因为是通用


另外,还有一个条件接口ConditionalConverter,可跟上面3个接口搭配组合使用,提供前置条件判断验证。


这套接口,解决了PropertyEditor做类型转换存在的所有缺陷,且具有非常高的灵活性和可扩展性。下面进入详细了解。


Converter


将源类型S转换为目标类型T。


@FunctionalInterface
public interface Converter<S, T> {
  T convert(S source);
}


它是个函数式接口,接口定义非常简单。适合1:1转换场景:可以将任意类型 转换为 任意类型。它的实现类非常多,部分截图如下:


image.png


值得注意的是:几乎所有实现类的访问权限都是default/private,只有少数几个是public公开的,下面我用代码示例来“近距离”感受一下。


代码示例


/**
 * Converter:1:1
 */
@Test
public void test() {
    System.out.println("----------------StringToBooleanConverter---------------");
    Converter<String, Boolean> converter = new StringToBooleanConverter();
    // trueValues.add("true");
    // trueValues.add("on");
    // trueValues.add("yes");
    // trueValues.add("1");
    System.out.println(converter.convert("true"));
    System.out.println(converter.convert("1"));
    // falseValues.add("false");
    // falseValues.add("off");
    // falseValues.add("no");
    // falseValues.add("0");
    System.out.println(converter.convert("FalSe"));
    System.out.println(converter.convert("off"));
    // 注意:空串返回的是null
    System.out.println(converter.convert(""));
    System.out.println("----------------StringToCharsetConverter---------------");
    Converter<String, Charset> converter2 = new StringToCharsetConverter();
    // 中间横杠非必须,但强烈建议写上   不区分大小写
    System.out.println(converter2.convert("uTf-8"));
    System.out.println(converter2.convert("utF8"));
}


运行程序,正常输出:

----------------StringToBooleanConverter---------------
true
true
false
false
null
----------------StringToCharsetConverter---------------
UTF-8
UTF-8


说明:StringToBooleanConverter/StringToCharsetConverter访问权限都是default,外部不可直接使用。此处为了做示例用到一个小技巧 -> 将Demo的报名调整为和转换器的一样,这样就可以直接访问。


关注点:true/on/yes/1都能被正确转换为true的,且对于英文字母来说一般都不区分大小写,增加了容错性(包括Charset的转换)。


不足


Converter用于解决1:1的任意类型转换,因此它必然存在一个不足:解决1:N转换问题需要写N遍,造成重复冗余代码。


譬如:输入是字符串,它可以转为任意数字类型,包括byte、short、int、long、double等等,如果用Converter来转换的话每个类型都得写个转换器,想想都麻烦有木有。


Spring早早就考虑到了该场景,提供了相应的接口来处理,它就是ConverterFactory<S, R>。




相关文章
|
8月前
|
存储 安全 Java
事件的力量:探索Spring框架中的事件处理机制
事件的力量:探索Spring框架中的事件处理机制
80 0
|
8月前
|
设计模式 前端开发 Java
【深入浅出Spring原理及实战】「夯实基础系列」360全方位渗透和探究SpringMVC的核心原理和运作机制(总体框架原理篇)
【深入浅出Spring原理及实战】「夯实基础系列」360全方位渗透和探究SpringMVC的核心原理和运作机制(总体框架原理篇)
79 0
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
87 2
|
17天前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
67 14
|
1月前
|
缓存 Java 数据库连接
深入探讨:Spring与MyBatis中的连接池与缓存机制
Spring 与 MyBatis 提供了强大的连接池和缓存机制,通过合理配置和使用这些机制,可以显著提升应用的性能和可扩展性。连接池通过复用数据库连接减少了连接创建和销毁的开销,而 MyBatis 的一级缓存和二级缓存则通过缓存查询结果减少了数据库访问次数。在实际应用中,结合具体的业务需求和系统架构,优化连接池和缓存的配置,是提升系统性能的重要手段。
55 4
|
2月前
|
Java 开发者 Spring
深入解析:Spring AOP的底层实现机制
在现代软件开发中,Spring框架的AOP(面向切面编程)功能因其能够有效分离横切关注点(如日志记录、事务管理等)而备受青睐。本文将深入探讨Spring AOP的底层原理,揭示其如何通过动态代理技术实现方法的增强。
76 8
|
8月前
|
Java 测试技术 开发者
Spring IoC容器通过依赖注入机制实现控制反转
【4月更文挑战第30天】Spring IoC容器通过依赖注入机制实现控制反转
70 0
|
5月前
|
Java 开发工具 Spring
Spring的Factories机制介绍
Spring的Factories机制介绍
111 1
|
6月前
|
安全 Java API
构建基于Spring Boot的REST API安全机制
构建基于Spring Boot的REST API安全机制
|
7月前
|
Java 应用服务中间件 Spring
解析Spring Boot自动装配的原理与机制
解析Spring Boot自动装配的原理与机制
133 4