简解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的配置途径见这里

相关文章
相关标签/搜索