Spring中的ConversionService源碼解析
ConversionService是什么
ConversionService是類型轉(zhuǎn)換服務的接口,最涉及的類有以下:

學習類型轉(zhuǎn)換服務之前我們先看看各個接口是做什么的
ConversionService接口
ConversionService接口的方法很簡單,就是判斷是否可以兩種類型是否可以轉(zhuǎn)換,和轉(zhuǎn)換方法

ConversionRegistry接口
從名字就可以看出ConverterRegistry是要實現(xiàn)轉(zhuǎn)換器注冊表的接口,添加和移除Converter和GenericConverter。

FormatterRegistry接口
FormatterRegistry接口是ConverterRegistry的子接口


在學這個接口之前要先了解Formatter是什么?
Formatter是什么?
Formatter是一種用于格式化和解析對象的接口,它可以將一個對象轉(zhuǎn)化為字符串,或?qū)⒁粋€字符串轉(zhuǎn)化為特定類型的對象。在Spring MVC中,F(xiàn)ormatter通常用于將HTTP請求中的參數(shù)綁定到Java對象上,或?qū)ava對象轉(zhuǎn)化為HTTP響應中的數(shù)據(jù)。

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接口就是對象轉(zhuǎn)換為String類型的接口,Parse接口就是將String類型轉(zhuǎn)換為特定類型對象的接口。在Spring中Formatter接口的實現(xiàn)也是非常多

所以如果不需要使用String類型和對象類型的轉(zhuǎn)換,使用GenericConversionService或DefaultConversionService就可以了
ConfigurableConversionService接口
ConfigurableConversionService繼承了ConversionService和ConversionRegistry接口,從類型轉(zhuǎn)換服務涉及的類可以看出ConversionService類型轉(zhuǎn)換服務都是需要和ConverterRegistry轉(zhuǎn)換器注冊表接口配合使用的。所以ConversionService的實現(xiàn)類都是實現(xiàn)了ConfigurableConversionService接口的。

Converter和GenericConverter的區(qū)別
Converter是一個通用的類型轉(zhuǎn)換器,它可以將一個類型轉(zhuǎn)換為另一個類型。它只能轉(zhuǎn)換一種類型,因此需要為每種類型都定義一個Converter。
GenericConverter是一個更通用的類型轉(zhuǎn)換器,它可以將多種類型轉(zhuǎn)換為多種類型。它可以處理多種不同的類型轉(zhuǎn)換場景,因此可以減少定義Converter的數(shù)量。GenericConverter可以在轉(zhuǎn)換過程中使用類型信息來決定如何轉(zhuǎn)換。
總的來說,Converter適用于單一類型轉(zhuǎn)換,而GenericConverter適用于多種類型轉(zhuǎn)換。 GenericConversionService也提供了一個內(nèi)部類ConverterAdapter,用來將Converter適配成GenericConverter,這里用了適配器模式
ConversionService的各個實現(xiàn)類有什么區(qū)別?又該如何選擇呢?
首先看DefaultFormattingConversionService的構(gòu)造方法,里面通過DefaultConversionService的靜態(tài)方法添加了默認的一些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);
}
測試結(jié)果
[1, 2, 3, 4]
true
{"user":{}}
com.zhouyu.service.OrderService@2bbf180e
到此這篇關(guān)于Spring中的ConversionService源碼解析的文章就介紹到這了,更多相關(guān)ConversionService源碼解析內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java Validation Api實現(xiàn)原理解析
這篇文章主要介紹了Java Validation Api實現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-09-09
詳解springMVC之與json數(shù)據(jù)交互方法
本篇文章主要介紹了詳解springMVC之與json數(shù)據(jù)交互方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05
在Java8與Java7中HashMap源碼實現(xiàn)的對比
這篇文章主要介紹了在Java8與Java7中HashMap源碼實現(xiàn)的對比,內(nèi)容包括HashMap 的原理簡單介紹、結(jié)合源碼在Java7中是如何解決hash沖突的以及優(yōu)缺點,結(jié)合源碼以及在Java8中如何解決hash沖突,balance tree相關(guān)源碼介紹,需要的朋友可以參考借鑒。2017-01-01
Java數(shù)字轉(zhuǎn)換工具類NumberUtil的使用
NumberUtil是一個功能強大的Java工具類,用于處理數(shù)字的各種操作,包括數(shù)值運算、格式化、隨機數(shù)生成和數(shù)值判斷,下面就來介紹一下NumberUtil的具體使用,感興趣的可以了解一下2025-02-02
springboot無法跳轉(zhuǎn)頁面的問題解決方案
這篇文章主要介紹了springboot無法跳轉(zhuǎn)頁面的問題解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-09-09

