Spring源码ConversionService解析

系列文章目录


文章目录

  • 系列文章目录
  • ConversionService是什么
  • ConversionService接口
  • ConversionRegistry接口
  • FormatterRegistry接口
  • ConfigurableConversionService接口
  • Converter和GenericConverter的区别
  • ConversionService的各个实现类有什么区别?又该如何选择呢?
  • ConversionService的使用示例


ConversionService是什么

ConversionService是类型转换服务的接口,最涉及的类有以下:
Spring源码ConversionService解析_第1张图片
学习类型转换服务之前我们先看看各个接口是做什么的

ConversionService接口

ConversionService接口的方法很简单,就是判断是否可以两种类型是否可以转换,和转换方法
Spring源码ConversionService解析_第2张图片

ConversionRegistry接口

从名字就可以看出ConverterRegistry是要实现转换器注册表的接口,添加和移除ConverterGenericConverter
Spring源码ConversionService解析_第3张图片

FormatterRegistry接口

FormatterRegistry接口是ConverterRegistry的子接口
在这里插入图片描述

Spring源码ConversionService解析_第4张图片
在学这个接口之前要先了解Formatter是什么?
Formatter是什么?
  Formatter是一种用于格式化和解析对象的接口,它可以将一个对象转化为字符串,或将一个字符串转化为特定类型的对象。在Spring MVC中,Formatter通常用于将HTTP请求中的参数绑定到Java对象上,或将Java对象转化为HTTP响应中的数据。
Spring源码ConversionService解析_第5张图片
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接口的实现也是非常多
Spring源码ConversionService解析_第6张图片
所以如果不需要使用String类型和对象类型的转换,使用GenericConversionServiceDefaultConversionService就可以了

ConfigurableConversionService接口

ConfigurableConversionService继承了ConversionServiceConversionRegistry接口,从类型转换服务涉及的类可以看出ConversionService类型转换服务都是需要和ConverterRegistry转换器注册表接口配合使用的。所以ConversionService的实现类都是实现了ConfigurableConversionService接口的。
在这里插入图片描述

Converter和GenericConverter的区别

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

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

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

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

首先看DefaultFormattingConversionService的构造方法,里面通过DefaultConversionService的静态方法添加了默认的一些Converter还有一些默认的Formatter,可以猜测到DefaultFormattingConversionServiceDefaultConversionService多添加了默认的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可以使用DefaultFormattingConversionServiceDefaultConversionService,如果不需要可以使用FormatterConversionServiceGenericConversionService

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,spring,java,mvc)