此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10! |
Spring Type Conversion
这core.convert
package 提供了一个通用的类型转换系统。系统定义
一个用于实现类型转换逻辑的 SPI 和一个用于执行类型转换的 API
运行。在 Spring 容器中,您可以使用此系统作为PropertyEditor
将外部化 bean 属性值字符串转换为
所需的属性类型。您还可以在应用程序中的任何位置使用公共 API
其中需要类型转换。
转换器 SPI
实现类型转换逻辑的 SPI 是简单且强类型的,如下所示 接口定义显示:
package org.springframework.core.convert.converter;
public interface Converter<S, T> {
T convert(S source);
}
要创建您自己的转换器,请实现Converter
接口和参数化S
作为您要转换的类型,以及T
作为您要转换为的类型。您也可以透明地应用这样的
转换器,如果集合或数组为S
需要是
转换为数组或集合T
,前提是委托数组或集合
转换器也已注册(其中DefaultConversionService
默认情况下)。
对于对convert(S)
,则保证 source 参数不为 null。你Converter
如果转换失败,可能会抛出任何未检查的异常。具体来说,它应该抛出一个IllegalArgumentException
以报告无效的源值。
请注意确保您的Converter
实现是线程安全的。
中提供了多个转换器实现core.convert.support
打包为
一种便利。其中包括从字符串到数字和其他常见类型的转换器。
以下列表显示了StringToInteger
类,这是一个典型的Converter
实现:
package org.springframework.core.convert.support;
final class StringToInteger implements Converter<String, Integer> {
public Integer convert(String source) {
return Integer.valueOf(source);
}
}
用ConverterFactory
当您需要集中整个类层次结构的转换逻辑时
(例如,从String
自Enum
对象),您可以实现ConverterFactory
,如以下示例所示:
package org.springframework.core.convert.converter;
public interface ConverterFactory<S, R> {
<T extends R> Converter<S, T> getConverter(Class<T> targetType);
}
参数化S
成为您要转换的类型,并且R
作为定义
可以转换为的类范围。然后实现getConverter(Class<T>)
,
哪里T
是R
.
考虑一下StringToEnumConverterFactory
举个例子:
package org.springframework.core.convert.support;
final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {
public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
return new StringToEnumConverter(targetType);
}
private final class StringToEnumConverter<T extends Enum> implements Converter<String, T> {
private Class<T> enumType;
public StringToEnumConverter(Class<T> enumType) {
this.enumType = enumType;
}
public T convert(String source) {
return (T) Enum.valueOf(this.enumType, source.trim());
}
}
}
用GenericConverter
当您需要更复杂的Converter
实现时,请考虑使用GenericConverter
接口。具有比Converter
一个GenericConverter
支持在多个源和目标之间进行转换
类型。此外,一个GenericConverter
提供了源和目标类型描述符
您可以在实现转化逻辑时使用。此类类型描述符使
类型转换由描述符源上的注释驱动(例如
字段或方法)或通过字段签名、方法中声明的通用信息
签名等。以下列表显示了GenericConverter
接口:
package org.springframework.core.convert.converter;
public interface GenericConverter {
public Set<ConvertiblePair> getConvertibleTypes();
Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}
要实现GenericConverter
有getConvertibleTypes()
返回支持的
源→目标类型对。然后实现convert(Object, TypeDescriptor,
TypeDescriptor)
以包含您的转化逻辑。来源TypeDescriptor
提供
访问保存要转换的值的源字段或方法。目标TypeDescriptor
提供对目标字段或方法的访问,其中转换后的值
是要设置的。
一个很好的例子GenericConverter
是一个在 Java 数组之间进行转换的转换器
和一个收藏。这样的ArrayToCollectionConverter
内省领域或方法
声明目标集合类型以解析集合的元素类型。这
让源数组中的每个元素在之前转换为集合元素类型
集合在目标字段上设置或提供给目标方法或构造函数。
因为GenericConverter 是一个比较复杂的 SPI 接口,你应该使用
只有在你需要的时候才会这样做。喜爱Converter 或ConverterFactory 对于基本型
转换需求。 |
用ConditionalGenericConverter
有时,您想要一个Converter
仅在特定条件成立时运行。为
例如,您可能想要运行一个Converter
仅当特定注释存在于
目标字段或方法,或者您可能想要运行Converter
仅当特定的
方法(例如static valueOf
方法)在目标类型上定义。ConditionalGenericConverter
是GenericConverter
和ConditionalConverter
接口,用于定义此类自定义匹配条件:
public interface ConditionalConverter {
boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
}
public interface ConditionalGenericConverter extends GenericConverter, ConditionalConverter {
}
一个很好的例子ConditionalGenericConverter
是一个IdToEntityConverter
转换
在持久实体标识符和实体引用之间。这样的IdToEntityConverter
仅当目标实体类型声明静态查找器方法(例如,findAccount(Long)
).您可以在matches(TypeDescriptor, TypeDescriptor)
.
这ConversionService
应用程序接口
ConversionService
定义一个统一的 API,用于执行类型转换逻辑
运行。转换器通常在以下立面接口后面运行:
package org.springframework.core.convert;
public interface ConversionService {
boolean canConvert(Class<?> sourceType, Class<?> targetType);
<T> T convert(Object source, Class<T> targetType);
boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);
Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}
最ConversionService
实现也实现ConverterRegistry
哪
提供用于注册转换器的SPI。在内部,一个ConversionService
实现委托给其注册的转换器来执行类型转换逻辑。
坚固的ConversionService
实现在core.convert.support
包。GenericConversionService
通用实现是否适合
在大多数环境中使用。ConversionServiceFactory
为提供便利的工厂
创造共同点ConversionService
配置。
配置ConversionService
一个ConversionService
是一个无状态对象,设计用于在应用程序中实例化
启动,然后在多个线程之间共享。在 Spring 应用程序中,您通常
配置一个ConversionService
实例(或ApplicationContext
).
Spring接住了这一点ConversionService
并在键入
转换需要由框架执行。您也可以注入此ConversionService
到你的任何 bean 中并直接调用它。
如果没有ConversionService 在 Spring 中注册,原始PropertyEditor -基于
系统。 |
注册默认值ConversionService
使用 Spring,添加以下 bean 定义
使用id
之conversionService
:
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean"/>
默认ConversionService
可以在字符串、数字、枚举、集合、
地图和其他常见类型。要使用
自己的自定义转换器,将converters
财产。属性值可以实现
任何Converter
,ConverterFactory
或GenericConverter
接口。
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="example.MyCustomConverter"/>
</set>
</property>
</bean>
使用ConversionService
在 Spring MVC 应用程序中。请参阅 Spring MVC 章节中的转换和格式化。
在某些情况下,您可能希望在转换过程中应用格式。看这FormatterRegistry
SPI有关使用详情FormattingConversionServiceFactoryBean
.
使用ConversionService
编程
要使用ConversionService
实例中,您可以注入引用
就像你对任何其他豆子一样。以下示例显示了如何执行此作:
-
Java
-
Kotlin
@Service
public class MyService {
private final ConversionService conversionService;
public MyService(ConversionService conversionService) {
this.conversionService = conversionService;
}
public void doIt() {
this.conversionService.convert(...)
}
}
@Service
class MyService(private val conversionService: ConversionService) {
fun doIt() {
conversionService.convert(...)
}
}
对于大多数用例,您可以使用convert
指定targetType
,但它
不适用于更复杂的类型,例如参数化元素的集合。
例如,如果要将List
之Integer
设置为List
之String
编程
您需要提供源和目标类型的正式定义。
幸运TypeDescriptor
提供了各种选项,使之变得简单,
如以下示例所示:
-
Java
-
Kotlin
DefaultConversionService cs = new DefaultConversionService();
List<Integer> input = ...
cs.convert(input,
TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(Integer.class)), (1)
TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(String.class))); (2)
1 | List<Integer> 类型描述符 |
2 | List<String> 类型描述符 |
val cs = DefaultConversionService()
val input: List<Integer> = ...
cs.convert(input,
TypeDescriptor.collection(List::class.java, TypeDescriptor.valueOf(Integer::class.java)), (1)
TypeDescriptor.collection(List::class.java, TypeDescriptor.valueOf(String::class.java))) (2)
1 | List<Integer> 类型描述符 |
2 | List<String> 类型描述符 |
请注意DefaultConversionService
自动注册转换器
适用于大多数环境。这包括集合转换器、标量
转换器和基本Object
-自-String
变换 器。您可以注册相同的转换器
与任何ConverterRegistry
通过使用 staticaddDefaultConverters
方法DefaultConversionService
类。
值类型的转换器被重用于数组和集合,因此有
无需创建特定的转换器即可从Collection
之S
设置为Collection
之T
,假设标准集合处理是适当的。