此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.2.0spring-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);
}

要创建您自己的转换器,请实现Converterinterface 和 parameterizeS作为您要转换的 type 并将T作为您要转换为的类型。您还可以透明地应用这样的 converter 如果是S需要 转换为T,前提是委托数组或集合 converter 也被注册了(它DefaultConversionService执行)。spring-doc.cadn.net.cn

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

中提供了几种转换器实现core.convert.supportpackage 设置为 一种便利。其中包括从字符串到数字和其他常见类型的转换器。 下面的清单显示了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>), 其中 T 是 R 的子类。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使源字段和目标字段可用 context 中,您可以在实施转化逻辑时使用。这样的上下文允许 类型转换由字段注释或在 字段签名。以下清单显示了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()返回支持的 source→target 类型对。然后实施convert(Object, TypeDescriptor, TypeDescriptor)以包含您的转化逻辑。来源TypeDescriptor提供 访问保存要转换的值的 source 字段。目标TypeDescriptor提供对要设置转换值的目标字段的访问。spring-doc.cadn.net.cn

一个很好的例子GenericConverter是在 Java 数组之间进行转换的转换器 和一个集合。这样的ArrayToCollectionConverter内省声明 目标集合类型,用于解析集合的元素类型。这样,每个 元素转换为 collection 元素类型,然后再将 collection 在 target 字段上设置。spring-doc.cadn.net.cn

因为GenericConverter是一个更复杂的 SPI 接口,您应该使用 它只在你需要的时候。喜爱ConverterConverterFactory用于基本型 转换需求。

ConditionalGenericConverter

有时,您需要一个Converter仅在特定条件为 true 时运行。为 示例中,您可能希望运行Converter仅当存在特定注释时 在 target 字段上,或者您可能希望运行Converter仅当特定方法 (例如static valueOf方法)在 Target 类上定义。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,用于在 运行。转换器通常在以下 Facade 接口后面运行: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);
}

ConversionServiceimplementations 还实现ConverterRegistry哪 提供用于注册转换器的 SPI。在内部,一个ConversionServiceimplementation 委托其注册的 converters 来执行类型转换逻辑。spring-doc.cadn.net.cn

一个强大的ConversionServiceimplementation 在core.convert.support包。GenericConversionService通用实现是否适合 在大多数环境中使用。ConversionServiceFactory提供便捷的工厂 创建通用ConversionService配置。spring-doc.cadn.net.cn

配置ConversionService

一个ConversionService是一个无状态对象,旨在在 application 中实例化 startup 的 URL,然后在多个线程之间共享。在 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.forObject(input), // List<Integer> type descriptor
	TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(String.class)));
val cs = DefaultConversionService()

val input: List<Integer> = ...
cs.convert(input,
		TypeDescriptor.forObject(input), // List<Integer> type descriptor
		TypeDescriptor.collection(List::class.java, TypeDescriptor.valueOf(String::class.java)))

请注意,DefaultConversionService自动注册 适用于大多数环境。这包括集合转换器、标量 转换器和 BasicObject-自-String变换 器。您可以注册相同的转换器 与任何ConverterRegistry通过使用静态addDefaultConverters方法上的DefaultConversionService类。spring-doc.cadn.net.cn

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