Spring中的ConversionService源码解析

 更新时间:2023年11月30日 09:45:16   作者:啊几  
这篇文章主要介绍了Spring中的ConversionService源码解析,ConversionService是类型转换服务的接口,从名字就可以看出ConverterRegistry是要实现转换器注册表的接口,添加和移除Converter和GenericConverter,需要的朋友可以参考下

ConversionService是什么

ConversionService是类型转换服务的接口,最涉及的类有以下:

在这里插入图片描述

学习类型转换服务之前我们先看看各个接口是做什么的

ConversionService接口

ConversionService接口的方法很简单,就是判断是否可以两种类型是否可以转换,和转换方法

在这里插入图片描述

ConversionRegistry接口

从名字就可以看出ConverterRegistry是要实现转换器注册表的接口,添加和移除Converter和GenericConverter。

在这里插入图片描述

FormatterRegistry接口

FormatterRegistry接口是ConverterRegistry的子接口

在这里插入图片描述

在这里插入图片描述

在学这个接口之前要先了解Formatter是什么?

Formatter是什么?

Formatter是一种用于格式化和解析对象的接口,它可以将一个对象转化为字符串,或将一个字符串转化为特定类型的对象。在Spring MVC中,Formatter通常用于将HTTP请求中的参数绑定到Java对象上,或将Java对象转化为HTTP响应中的数据。

在这里插入图片描述

Formatter接口继承了Printer和Parse两个接口

public interface Printer<T> {

	String print(T object, Locale locale);
	
}
public interface Parser<T> {

	T parse(String text, Locale locale) throws ParseException;

}

Printer接口就是对象转换为String类型的接口,Parse接口就是将String类型转换为特定类型对象的接口。在Spring中Formatter接口的实现也是非常多

在这里插入图片描述

所以如果不需要使用String类型和对象类型的转换,使用GenericConversionService或DefaultConversionService就可以了

ConfigurableConversionService接口

ConfigurableConversionService继承了ConversionService和ConversionRegistry接口,从类型转换服务涉及的类可以看出ConversionService类型转换服务都是需要和ConverterRegistry转换器注册表接口配合使用的。所以ConversionService的实现类都是实现了ConfigurableConversionService接口的。

在这里插入图片描述

Converter和GenericConverter的区别

Converter是一个通用的类型转换器,它可以将一个类型转换为另一个类型。它只能转换一种类型,因此需要为每种类型都定义一个Converter。

GenericConverter是一个更通用的类型转换器,它可以将多种类型转换为多种类型。它可以处理多种不同的类型转换场景,因此可以减少定义Converter的数量。GenericConverter可以在转换过程中使用类型信息来决定如何转换。

总的来说,Converter适用于单一类型转换,而GenericConverter适用于多种类型转换。 GenericConversionService也提供了一个内部类ConverterAdapter,用来将Converter适配成GenericConverter,这里用了适配器模式

ConversionService的各个实现类有什么区别?又该如何选择呢?

首先看DefaultFormattingConversionService的构造方法,里面通过DefaultConversionService的静态方法添加了默认的一些Converter还有一些默认的Formatter,可以猜测到DefaultFormattingConversionService比DefaultConversionService多添加了默认的Formatter

public DefaultFormattingConversionService(
			@Nullable StringValueResolver embeddedValueResolver, boolean registerDefaultFormatters) {

		if (embeddedValueResolver != null) {
			setEmbeddedValueResolver(embeddedValueResolver);
		}
		DefaultConversionService.addDefaultConverters(this);
		if (registerDefaultFormatters) {
			addDefaultFormatters(this);
		}
	}

下面是默认添加的一些Converter

	public static void addDefaultConverters(ConverterRegistry converterRegistry) {
		addScalarConverters(converterRegistry);
		addCollectionConverters(converterRegistry);

		converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry));
		converterRegistry.addConverter(new StringToTimeZoneConverter());
		converterRegistry.addConverter(new ZoneIdToTimeZoneConverter());
		converterRegistry.addConverter(new ZonedDateTimeToCalendarConverter());

		converterRegistry.addConverter(new ObjectToObjectConverter());
		converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry));
		converterRegistry.addConverter(new FallbackObjectToStringConverter());
		converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService) converterRegistry));
	}

下面是默认添加的一些Formatter

	public static void addDefaultFormatters(FormatterRegistry formatterRegistry) {
		// Default handling of number values
		formatterRegistry.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());

		// Default handling of monetary values
		if (jsr354Present) {
			formatterRegistry.addFormatter(new CurrencyUnitFormatter());
			formatterRegistry.addFormatter(new MonetaryAmountFormatter());
			formatterRegistry.addFormatterForFieldAnnotation(new Jsr354NumberFormatAnnotationFormatterFactory());
		}

		// Default handling of date-time values

		// just handling JSR-310 specific date and time types
		new DateTimeFormatterRegistrar().registerFormatters(formatterRegistry);

		if (jodaTimePresent) {
			// handles Joda-specific types as well as Date, Calendar, Long
			new org.springframework.format.datetime.joda.JodaTimeFormatterRegistrar().registerFormatters(formatterRegistry);
		}
		else {
			// regular DateFormat-based Date, Calendar, Long converters
			new DateFormatterRegistrar().registerFormatters(formatterRegistry);
		}
	}

所以如果要使用Spring自带的一些Formatter和Converter可以使用DefaultFormattingConversionService比DefaultConversionService,如果不需要可以使用FormatterConversionService或GenericConversionService。

ConversionService的使用示例

	public static void main(String[] args) {

		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
		UserService userService = (UserService) applicationContext.getBean("userService");

		FormattingConversionService conversionService = new DefaultFormattingConversionService();
		
		//String -> ArrayList
		System.out.println(conversionService.convert("1,2,3,4", ArrayList.class));
		
		//boolean -> String
		System.out.println(conversionService.convert(true,String.class));
		
		//自定义了一个格式化器,OrderService -> String ,String -> OrderService
		conversionService.addFormatter(new Formatter<OrderService>() {
			private ObjectMapper objectMapper = new ObjectMapper();
			@Override
			public String print(OrderService object, Locale locale) {
				try {
					return objectMapper.writeValueAsString(object);
				} catch (JsonProcessingException e) {
					throw new RuntimeException(e);
				}
			}

			@Override
			public OrderService parse(String text, Locale locale) throws ParseException {
				try {
					return  objectMapper.readValue(text,OrderService.class);
				} catch (JsonProcessingException e) {
					throw new RuntimeException(e);
				}
			}
		});
		String result = conversionService.convert(userService.getOrderService(),String.class);
		System.out.println(result);
		OrderService orderService = conversionService.convert(result, OrderService.class);
		System.out.println(orderService);
	}


测试结果

[1, 2, 3, 4]
true
{"user":{}}
com.zhouyu.service.OrderService@2bbf180e

到此这篇关于Spring中的ConversionService源码解析的文章就介绍到这了,更多相关ConversionService源码解析内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

最新评论