Spring中的ConversionService源碼解析
ConversionService是什么
ConversionService是類型轉(zhuǎn)換服務(wù)的接口,最涉及的類有以下:
學(xué)習(xí)類型轉(zhuǎn)換服務(wù)之前我們先看看各個接口是做什么的
ConversionService接口
ConversionService接口的方法很簡單,就是判斷是否可以兩種類型是否可以轉(zhuǎn)換,和轉(zhuǎn)換方法
ConversionRegistry接口
從名字就可以看出ConverterRegistry是要實現(xiàn)轉(zhuǎn)換器注冊表的接口,添加和移除Converter和GenericConverter。
FormatterRegistry接口
FormatterRegistry接口是ConverterRegistry的子接口
在學(xué)這個接口之前要先了解Formatter是什么?
Formatter是什么?
Formatter是一種用于格式化和解析對象的接口,它可以將一個對象轉(zhuǎn)化為字符串,或?qū)⒁粋€字符串轉(zhuǎn)化為特定類型的對象。在Spring MVC中,F(xiàn)ormatter通常用于將HTTP請求中的參數(shù)綁定到Java對象上,或?qū)ava對象轉(zhuǎn)化為HTTP響應(yīng)中的數(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)換服務(wù)涉及的類可以看出ConversionService類型轉(zhuǎn)換服務(wù)都是需要和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)方法添加了默認(rèn)的一些Converter還有一些默認(rèn)的Formatter,可以猜測到DefaultFormattingConversionService比DefaultConversionService多添加了默認(rèn)的Formatter
public DefaultFormattingConversionService( @Nullable StringValueResolver embeddedValueResolver, boolean registerDefaultFormatters) { if (embeddedValueResolver != null) { setEmbeddedValueResolver(embeddedValueResolver); } DefaultConversionService.addDefaultConverters(this); if (registerDefaultFormatters) { addDefaultFormatters(this); } }
下面是默認(rèn)添加的一些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)); }
下面是默認(rèn)添加的一些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)原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下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-01Java數(shù)字轉(zhuǎn)換工具類NumberUtil的使用
NumberUtil是一個功能強大的Java工具類,用于處理數(shù)字的各種操作,包括數(shù)值運算、格式化、隨機數(shù)生成和數(shù)值判斷,下面就來介紹一下NumberUtil的具體使用,感興趣的可以了解一下2025-02-02springboot無法跳轉(zhuǎn)頁面的問題解決方案
這篇文章主要介紹了springboot無法跳轉(zhuǎn)頁面的問題解決方案,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-09-09