Converter
概述
在使用系统的过程中,我们经常面临着类型转换的问题。比如在 properties 文件中保存的变量是字符串类型,但是注入时需要注入 Long 类型等等。为了方便地解决这些问题,本类库在 central.convert
包下定义了一套完整的类型转换系统。该系统使用 SPI 机制去实现类型转换器的注册逻辑,并支持在运行时执行类型转换逻辑。开发者还可以通过容器注入的方式去添加一些自定义的类型转换器。
Converter Interface
Converter
接口是类型转换的上层接口,本类库提供了该接口的标准实现类 GenericConverter
。开发者通过该接口可以方便地完成类型转换工作。Converter
的接口定义如下:
interface Converter {
/**
* 是否支持将源类型转换为指定类型
*
* @param source 源类型
* @param target 目标类型
*/
fun support(source: Class<*>, target: Class<*>): Boolean
/**
* 将源对象转换为指定类型
*/
@Throws(ConvertException::class)
fun <T> convert(source: Any?, target: Class<T>): T?
}
开发者在使用时,可以参考以下代码片段:
class TestComponent {
@Autowired
private lateinit var converter: Converter
fun test() {
val source: String = "1234"
// 判断是否支持类型转换
if (converter.support(source::class.java, Int::class.java)) {
// 执行转换逻辑
val target: Int = converter.convert(source, Int::class.java)
}
}
}
Custom TypeConverter
TypeConverter Interface
TypeConverter
是实现类型转换逻辑的基本单元。本类库在 central.convert.support.impl
包下提供了很多内置的类型转换器。开发者在自定义类型转换器时,也同样需要实现该接口。接口定义如下:
interface TypeConverter<T> {
/**
* 判断当前转换器是否支持转换源类型
*
* @param source 源类型
*/
fun support(source: Class<*>): Boolean
/**
* 执行转换逻辑
*/
@Throws(ConvertException::class)
fun convert(source: Any): T?
}
开发者可以参考内置的类型转换器去实现自定义类型转换器,如:
class IntegerConverter : Converter<Int> {
/**
* 判断当前转换器是否支持转换源类型
*
* @param source 源类型
*/
override fun support(source: Class<*>): Boolean = when {
source == Int::class.javaObjectType -> true
Number::class.java.isAssignableFrom(source) -> true
source == String::class.java -> true
else -> false
}
/**
* 执行转换逻辑
*/
override fun convert(source: Any): Int? = when (source) {
is Int -> source
is Number -> source.toInt()
is String -> source.toInt()
else -> throw ConvertException(source, Int::class.javaObjectType)
}
}
SPI Register
GenericConverter
实现了通过 SPI 机制去加载自定义类型转换器的逻辑。开发者只需要在 resource
目录下新建 META-INF/central.convert.Converter.imports
文件,文件内容如下:
imports=your.converter.full.path.CustomConverter
GenericConverter
在创建时,会自动寻找该文件并加载指定的类型转换器。
提示
通过 SPI 的方式注册类型转换器后,后续所有新建的 GenericConverter
实例都将自动加载这些转换器。
Container Register
在 IoC 容器中,同时也内置了 Converter 的实现。如果开发者使用了 IoC 容器,那么开发者只需要将类型转换器注册到容器中,IoC 容器会自动将该转换器注册到内置的 Converter 实例中。如:
@Configuration
@Import(CustomConverter::class)
class ApplicationConfiguration {
}
提示
通过 IoC 容器的方式注册的类型转换器,只会注册到容器内置的 GenericConverter
实例,而开发者自己新建的 GenericConverter
实例是没有注册这些转换器的。