spring · 23 4 月, 2021 0

Spring数据转换

Spring数据转换

使用场景

场景 基于JavaBeans接口的类型转换实现 Spring3.0+通用类型转换实现
数据绑定 YES YES
BeanWrapper YES YES
Bean属性类型转换 YES YES
外部化属性类型转换 NO YES

基于JavaBeans接口的类型转换

  • 核心职责

    • 将String类型的内容转换为目标类型的对象

  • 扩展原理

    • Spring框架将文本内容传递到PropertyEditor实现的setAsText(String)方法

    • PropertyEditor#setAsText(String)方法实现将String类型转换为目标类型的对象

    • 将目标类型的对象传入PropertyEditor#setValue(Object)方法

    • PropertyEditor#setValue(Object)方法实现需要临时存储传入对象

    • Spring框架将通过PropertyEditor#getValue()获取类型转换后的对象

Spring内建扩展

  • 内建扩展(org.springframework.beans.propertyeditors)

    转换场景 实现类
    String -> Byte数组 ByteArrayPropertyEditor
    String -> Char CharacterEditor
    String -> Char[] CharArrayPropertyEditor
    String -> Charset CharsetEditor
    String -> Class ClassEditor
    String -> Currency CurrencyEditor

自定义PropertyEditor扩展

  • 扩展模式

    • 扩展java.beans.PropertyEditorSupport

  • 实现org.springframework.beans.PropertyEditorRegistrar

    • 实现registerCustomEditors(org.springframework.beans.PropertyEditorRegsitry)

    • PropertyEditorRegsitrar实现注册为Spring Bean

  • org.springframework.bean.PropertyEditorRegistry注册自定义PropertyEditor实现

    • 通用类型实现regsiterCustomEditor(Class<?>, PropertyEditor)

    • Java Bean属性类型实现: registerCustomEditor(Class<?>, String, PropertyEditor)

Spring PropertyEditor的设计缺陷

  • 违反单一职责原则

    • java.beans.PropertyEditor接口职责太多,除了类型转换,还包括Java Beans事件和Java GUI 交互

    • java.bean.PropertyEditor 实现类型局限

      • 来源类型只能为java.lang.String类型

    • java.beans.PropertyEditor实现缺陷类型安全

      • 除了实现命名可以表达语义,实现类无法感知目标转换类型

Spring 3 通用类型转换接口

  • 类型转换接口 – Converter<S, T>

    • 泛型参数S: 来源类型, 参数T: 目标类型

    • 核心方法: T convert(S)

  • 通用类型转换接口 org.springframework.core.convert.converter.GenericConverter

    • 核心方法: convert(Object, TypeDescriptor, TypeDescritor)

    • 配对类型: org.springframework.core.convert.converter.GenericConverter.ConvertiblePair

    • 类型描述:org.springframework.core.convert.TyepDescriptor

Converter接口的局限性

  • 局限一: 缺少Source Type 和Target Type前置判断

    • 应对: 增加org.springframework.core.convert.converter.ConditionalConverter实现

  • 局限二: 仅能转换单一的Source Type 和Target Type

    • 应对: 使用org.springframework.core.convert.converter.GenericConverter代替

org.springframework.core.convert.converter.GenericConverter

核心要素 说明
使用场景 用于复合类型转换场景,比如Collection, Map, 数组等
转换范围 Set<ConveriblePair> getConvertibleType()
配对类型 org.springframework.core.convert.converter.GenericConverter.ConvertiblePair
转换方法 convert(Object, TypeDescriptor, TypeDescriptor)
类型描述 org.springframework.core.convert.TypeDescriptor

优化GenericConverter接口

  • GenericConverter局限性

    • 缺少Source TypeTarget Type前置判断

    • 单一类型转换实现复杂

  • GenericConverter优化接口 – ConditionalGenericConverter

    • 复合类型转换: org.springframework.core.convert.converter.GenericConverter

    • 条件类型转换: org.springframework.core.convert.converter.ConditionalConverter

扩展Spring 类型转换器

  • 实现转换器接口

    • org.springframework.core.convert.converter.Converter

    • org.springframework.core.convert.converter.ConverterFactory

    • org.springframework.core.convert.converter.GenericConverter

  • 注册转发器实现

    • 通过ConversionServiceFactoryBeanSpring Bean

    • 通过org.springframework.core.convert.converter.ConversionService API

统一类型转换服务

  • org.springframework.core.convert.ConversionService

    实现类型 说明
    GenericConversionService 通用ConversionService模板实现,不内置转换器实现
    DefaultConversionService 基础ConversionService实现,内置常用转化器实现
    FormattingConversionService 通用Formatter + GenericConversionService实现,不内置转化器和Formatter实现
    DefaultFormattingConversionService DefaultConversionService + 格式化, 实现(如: JSR-354)

    ConversionService作为依赖

    • 类型转换器底层接口 – org.springframework.beans.TypeConverter

      • 起始版本: Spring 2.0

      • 核心方法 – convertIfNecessary 重载方法

      • 抽象实现 – TypeConverterSupport

      • 简单实现 – SimpleTypeConverter

    • 类型转换器底层抽象实现 – org.springframework.beans.TypeConverterSupport

      • 实现接口 – TypeConverter

      • 扩展实现 – PropertyEditorRegistrySupport

      • 委派实现 – TypeConverterDelegate

    • 转换器委派底层实现 – TypeConverterDelegate

      • 构造来源 – AbstractNestablePropertyAccessor实现

        • BeanWrapperImpl

      • 依赖 – PropertyEditor实现

        • 默认内建实现 – PropertyEditorRegistrySupport #registerDefaultEditor

      • 可选依赖

        • ConversionService