此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10spring-doc.cadn.net.cn

Spring Type Conversion

core.convertpackage 提供了一个通用的类型转换系统。系统定义 一个用于实现类型转换逻辑的 SPI 和一个用于执行类型转换的 API 运行。在 Spring 容器中,您可以使用此系统作为PropertyEditor将外部化 bean 属性值字符串转换为 所需的属性类型。您还可以在应用程序中的任何位置使用公共 API 其中需要类型转换。spring-doc.cadn.net.cn

转换器 SPI

实现类型转换逻辑的 SPI 是简单且强类型的,如下所示 接口定义显示:spring-doc.cadn.net.cn

package org.springframework.core.convert.converter;

public interface Converter<S, T> {

	T convert(S source);
}

要创建您自己的转换器,请实现Converter接口和参数化S作为您要转换的类型,以及T作为您要转换为的类型。您也可以透明地应用这样的 转换器,如果集合或数组为S需要是 转换为数组或集合T,前提是委托数组或集合 转换器也已注册(其中DefaultConversionService默认情况下)。spring-doc.cadn.net.cn

对于对convert(S),则保证 source 参数不为 null。你Converter如果转换失败,可能会抛出任何未检查的异常。具体来说,它应该抛出一个IllegalArgumentException以报告无效的源值。 请注意确保您的Converter实现是线程安全的。spring-doc.cadn.net.cn

中提供了多个转换器实现core.convert.support打包为 一种便利。其中包括从字符串到数字和其他常见类型的转换器。 以下列表显示了StringToInteger类,这是一个典型的Converter实现:spring-doc.cadn.net.cn

package org.springframework.core.convert.support;

final class StringToInteger implements Converter<String, Integer> {

	public Integer convert(String source) {
		return Integer.valueOf(source);
	}
}

ConverterFactory

当您需要集中整个类层次结构的转换逻辑时 (例如,从StringEnum对象),您可以实现ConverterFactory,如以下示例所示:spring-doc.cadn.net.cn

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>), 哪里TR.spring-doc.cadn.net.cn

考虑一下StringToEnumConverterFactory举个例子:spring-doc.cadn.net.cn

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接口:spring-doc.cadn.net.cn

package org.springframework.core.convert.converter;

public interface GenericConverter {

	public Set<ConvertiblePair> getConvertibleTypes();

	Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}

要实现GenericConvertergetConvertibleTypes()返回支持的 源→目标类型对。然后实现convert(Object, TypeDescriptor, TypeDescriptor)以包含您的转化逻辑。来源TypeDescriptor提供 访问保存要转换的值的源字段或方法。目标TypeDescriptor提供对目标字段或方法的访问,其中转换后的值 是要设置的。spring-doc.cadn.net.cn

一个很好的例子GenericConverter是一个在 Java 数组之间进行转换的转换器 和一个收藏。这样的ArrayToCollectionConverter内省领域或方法 声明目标集合类型以解析集合的元素类型。这 让源数组中的每个元素在之前转换为集合元素类型 集合在目标字段上设置或提供给目标方法或构造函数。spring-doc.cadn.net.cn

因为GenericConverter是一个比较复杂的 SPI 接口,你应该使用 只有在你需要的时候才会这样做。喜爱ConverterConverterFactory对于基本型 转换需求。

ConditionalGenericConverter

有时,您想要一个Converter仅在特定条件成立时运行。为 例如,您可能想要运行一个Converter仅当特定注释存在于 目标字段或方法,或者您可能想要运行Converter仅当特定的 方法(例如static valueOf方法)在目标类型上定义。ConditionalGenericConverterGenericConverterConditionalConverter接口,用于定义此类自定义匹配条件:spring-doc.cadn.net.cn

public interface ConditionalConverter {

	boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
}

public interface ConditionalGenericConverter extends GenericConverter, ConditionalConverter {
}

一个很好的例子ConditionalGenericConverter是一个IdToEntityConverter转换 在持久实体标识符和实体引用之间。这样的IdToEntityConverter仅当目标实体类型声明静态查找器方法(例如,findAccount(Long)).您可以在matches(TypeDescriptor, TypeDescriptor).spring-doc.cadn.net.cn

ConversionService应用程序接口

ConversionService定义一个统一的 API,用于执行类型转换逻辑 运行。转换器通常在以下立面接口后面运行:spring-doc.cadn.net.cn

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实现委托给其注册的转换器来执行类型转换逻辑。spring-doc.cadn.net.cn

坚固的ConversionService实现在core.convert.support包。GenericConversionService通用实现是否适合 在大多数环境中使用。ConversionServiceFactory为提供便利的工厂 创造共同点ConversionService配置。spring-doc.cadn.net.cn

配置ConversionService

一个ConversionService是一个无状态对象,设计用于在应用程序中实例化 启动,然后在多个线程之间共享。在 Spring 应用程序中,您通常 配置一个ConversionService实例(或ApplicationContext). Spring接住了这一点ConversionService并在键入 转换需要由框架执行。您也可以注入此ConversionService到你的任何 bean 中并直接调用它。spring-doc.cadn.net.cn

如果没有ConversionService在 Spring 中注册,原始PropertyEditor-基于 系统。

注册默认值ConversionService使用 Spring,添加以下 bean 定义 使用idconversionService:spring-doc.cadn.net.cn

<bean id="conversionService"
	class="org.springframework.context.support.ConversionServiceFactoryBean"/>

默认ConversionService可以在字符串、数字、枚举、集合、 地图和其他常见类型。要使用 自己的自定义转换器,将converters财产。属性值可以实现 任何Converter,ConverterFactoryGenericConverter接口。spring-doc.cadn.net.cn

<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 章节中的转换和格式化spring-doc.cadn.net.cn

在某些情况下,您可能希望在转换过程中应用格式。看FormatterRegistrySPI有关使用详情FormattingConversionServiceFactoryBean.spring-doc.cadn.net.cn

使用ConversionService编程

要使用ConversionService实例中,您可以注入引用 就像你对任何其他豆子一样。以下示例显示了如何执行此作:spring-doc.cadn.net.cn

@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,但它 不适用于更复杂的类型,例如参数化元素的集合。 例如,如果要将ListInteger设置为ListString编程 您需要提供源和目标类型的正式定义。spring-doc.cadn.net.cn

幸运TypeDescriptor提供了各种选项,使之变得简单, 如以下示例所示:spring-doc.cadn.net.cn

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类。spring-doc.cadn.net.cn

值类型的转换器被重用于数组和集合,因此有 无需创建特定的转换器即可从CollectionS设置为CollectionT,假设标准集合处理是适当的。spring-doc.cadn.net.cn