簡解Spring的BeanWrapper、DataBinder、ConversionService、Formatter

Spring官方文檔有專門一個章節闡述了BeanWrapper、DataBinder、ConversionService、Formatterhtml

同時也有相關章節闡述了Spring MVC中對其的運用:java

  1. Section 22.16.3, 「Conversion and Formatting」git

  2. Customizing data binding with @InitBindergithub

不過很遺憾,官方文檔對於如何在Standalone app和Spring MVC中應用這些東西講的並非很明白,本文旨在對BeanWrapper、DataBinder、ConversionService、Formatter作一個簡單的概念解釋,有助於開發人員利用這些工具。web

基礎概念

如下先講解釋一下這四個東西分別是幹嗎的。spring

BeanWrapper

BeanWrapper是一個方便開發人員使用字符串來對Java Bean的屬性執行get、set操做的工具類。好比:mvc

Foo foo = new Foo();
BeanWrapperImpl fooWrapper = new BeanWrapperImpl(foo);
fooWrapper.setPropertyValue("intProperty", "1");
Object intProperty = fooWrapper.getPropertyValue("intProperty");

它爲那些UI類app提供了極大的便利,由於這類app大部分狀況下都是以字符串和用戶交互的,這個很好理解吧,用戶看到的數據都是文字,而不是一堆二進制。oracle

BeanWrapper內部使用了兩種機制:app

  1. PropertyEditor。PropertyEditor隸屬於Java Bean規範。PropertyEditor只提供了String <-> Object的轉換。工具

  2. ConversionService。Spring自3.0以後提供的替代PropertyEditor的機制,後面會詳細說。

按照Spring官方文檔的說法,當容器內沒有註冊ConversionService的時候,會退回使用PropertyEditor機制。

ConversionService

ConversionService及其相關一套類型轉換機制是一套通用的類型轉換SPI,相比PropertyEditor只提供String<->Object的轉換,ConversionService可以提供任意Object<->Object的轉換。

因此咱們能夠猜想,Spring爲什麼要使用ConversionService替代PropertyEditor有三個緣由:

  1. ConversionService功能更強大,支持的類型轉換範圍更廣。

  2. ConverterFactory支持一整個class hierarchy的轉換(也就是多態),PropertyEditor則不行。

  3. Java Bean這個規範最初是和Java GUI(Swing)一塊兒誕生的,PropertyEditor接口裏有大量和GUI相關的方法,顯然已通過時了。順便提一句,Java Bean和POJO不是一個概念,Java Bean不只有setter、getter,還有一系列和Java GUI配套的東西。

Formatter

Formatter SPI是另一套和PropertyEditor相似的,String<->Object的轉換機制,可是有兩個優勢:

  1. 接口更乾淨,沒有關於GUI的部分,只有printparse兩個方法。

  2. 基於註解,支持同一類型的屬性根據不一樣的格式來作String<->Object的轉換。好比日期類型,一個字段的格式是yyyy-MM-dd,另外一個格式是yyyyMMdd,若是利用PropertyEditor是比較麻煩,可是在這裏就能夠利用@DateTimeFormat來達到這個效果。

Spring提供了DefaultFormattingConversionService來支持Formatter SPI,也就是說若是要使用Formatter SPI,依然能夠利用ConversionService接口。

注意:Formatter SPI必須基於註解纔可使用,這點和ConversionService基於類型不一樣。

DataBinder

DataBinder主要提供了兩個功能:

  1. 利用BeanWrapper,給對象的屬性設值

  2. 在設值的同時作Validation

由於Validation不在本文探討範圍只能所以不作詳述了。

關係

本小節講一下BeanWrapper、DataBinder、ConversionService、Formatter之間的關係,以及Spring內部對它們的使用。

四者關係圖

圖片描述

注意上圖中ConversionService有兩種實現:

  1. DefaultConversionService,不支持Formatter SPI

  2. DefaultFormattingConversionService,支持Formatter SPI

也就是說,若是要支持Formatter SPI,只須要讓BeanWrapper切換使用不一樣的ConversionService便可。

Core Context的使用

圖片描述

Spring Core Context其實也使用ConversionService,可是是非強制的。

Spring在讀取xml配置文件的時候,由於xml文件其實是一個文本文件,全部值的設置都是String,這個時候若是給bean的複雜類型屬性設置值,它會用到PropertyEditor或ConversionService。

好比下面例子中的color屬性是Color類型,這時就會利用到PropertyEditor和ConversionService:

<bean id="someBean" class="a.b.c.SomeBean">
    <property name="color" value="red"/>
</bean>

讓Spring Core Context使用conversionService的方式很簡單,配置一個名字叫作conversionService的Bean便可。詳情見9.5.5 Configuring a ConversionService

須要注意的是,由於這個Bean是在很是早的時候就被使用的(AbstractApplicationContext#L834),所以它最好不要依賴過多的其餘的Bean,避免形成啓動失敗。

MVC的使用

圖片描述

Spring MVC對於conversionService的使用比較特殊,它本身會註冊一個名字叫作mvcConversionService類型爲DefaultFormattingConversionService的Bean(代碼在WebMvcConfigurationSupport#mvcConversionService)。所以會存在如下陷阱:

  1. 若是Core Context中也定義了一個ConversionService,那麼在MVC環境下,會有兩個ConversionService的Bean。

  2. 針對Core Context的ConversionService作的Customize如FormatterRegistrarConverterRegistryFormatterRegistryConversionServiceFactoryBeanFormattingConversionServiceFactoryBean是不會應用到MVC的那個ConversionService上。 對於mvcConversionService的配置途徑見這裏

相關文章
相關標籤/搜索