微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

spring 22 对象绑定与类型转换

底层第一套转换接口与实现

classDiagram Formatter --|> Printer Formatter --|> Parser class Converters { Set~GenericConverter~ } class Converter class ConversionService class FormattingConversionService ConversionService <|-- FormattingConversionService FormattingConversionService o-- Converters Printer --> Adapter1 Adapter1 --> Converters Parser --> Adapter2 Adapter2 --> Converters Converter --> Adapter3 Adapter3 --> Converters <<interface>> Formatter <<interface>> Printer <<interface>> Parser <<interface>> Converter <<interface>> ConversionService
  • Printer 把其它类型转为 String
  • Parser 把 String 转为其它类型
  • Formatter 综合 Printer 与 Parser 功能
  • Converter 把类型 S 转为类型 T
  • Printer、Parser、Converter 经过适配转换成 GenericConverter 放入 Converters 集合
  • FormattingConversionService 利用其它们实现转换

底层第二套转换接口

classDiagram propertyeditorRegistry o-- "多" propertyeditor <<interface>> propertyeditorRegistry <<interface>> propertyeditor

高层接口与实现

classDiagram TypeConverter <|-- SimpleTypeConverter TypeConverter <|-- BeanWrapperImpl TypeConverter <|-- DirectFieldAccessor TypeConverter <|-- ServletRequestDataBinder SimpleTypeConverter --> TypeConverterDelegate BeanWrapperImpl --> TypeConverterDelegate DirectFieldAccessor --> TypeConverterDelegate ServletRequestDataBinder --> TypeConverterDelegate TypeConverterDelegate --> ConversionService TypeConverterDelegate --> propertyeditorRegistry <<interface>> TypeConverter <<interface>> ConversionService <<interface>> propertyeditorRegistry
  • 它们都实现了 TypeConverter 这个高层转换接口,在转换时,会用到 TypeConverter Delegate 委派ConversionService 与 propertyeditorRegistry 真正执行转换(Facade 门面模式)
    • 首先看是否有自定义转换器, @InitBinder 添加的即属于这种 (用了适配器模式把 Formatter 转为需要的 propertyeditor)
    • 再看有没有 ConversionService 转换
    • 再利用认的 propertyeditor 转换
    • 最后有一些特殊处理
  • SimpleTypeConverter 仅做类型转换
  • BeanWrapperImpl 为 bean 的属性赋值,当需要时做类型转换,走 Property
  • DirectFieldAccessor 为 bean 的属性赋值,当需要时做类型转换,走 Field
  • DataBinder 普通环境下的属性数据绑定类型转换
  • ServletRequestDataBinder 为 bean 的属性执行绑定,当需要时做类型转换,根据 directFieldAccess 选择走 Property 还是 Field,具备校验与获取校验结果功能

类型转换与数据绑定

点击查看代码
 //仅有类型转换功能
        SimpleTypeConverter converter = new SimpleTypeConverter();
        System.out.println(converter.convertIfNecessary("11", int.class));
        System.out.println(converter.convertIfNecessary("2011/01/02", Date.class));
//类型转换与数据绑定 ,根据反射,用 set 方法为 bean 属性赋值
        BeanWrapperImpl beanWrapper = new BeanWrapperImpl();
        S22Bean1 s22Bean1 = new S22Bean1();
        beanWrapper.setBeanInstance(s22Bean1);
        beanWrapper.setPropertyValue("name",13);
        beanWrapper.setPropertyValue("age","32");
        beanWrapper.setPropertyValue("date","2011/11/20");
        System.out.println(s22Bean1);
//类型转换与数据绑定, 利用反射,直接赋值给 bean 的属性,不需要 set 方法
        S22Bean2 s22Bean2 = new S22Bean2();
        DirectFieldAccessor fieldAccessor = new DirectFieldAccessor(s22Bean2);
        fieldAccessor.setPropertyValue("name",22);
        fieldAccessor.setPropertyValue("age","19");
        System.out.println(s22Bean2);
 //类型转换与数据绑定,根据 DirectFieldAccess 存不存在判断用哪种方法数据绑定  认用 set 方法
        S22Bean2 s22Bean2 = new S22Bean2();
        DataBinder dataBinder = new DataBinder(s22Bean2);
        dataBinder.initDirectFieldAccess();
        MutablePropertyValues propertyValues = new MutablePropertyValues();
        propertyValues.add("name", 34);
        propertyValues.add("age", "12");
        dataBinder.bind(propertyValues);
        System.out.println(s22Bean2);
//类型转换与数据绑定,根据 DirectFieldAccess 存不存在判断用哪种方法数据绑定  认用 set 方法
        S22Bean2 s22Bean2 = new S22Bean2();
        DataBinder dataBinder = new ServletRequestDataBinder(s22Bean2);
        //可直接对属性进行绑定
        dataBinder.initDirectFieldAccess();
        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setParameter("name","13");
        request.setParameter("age","13");
        request.setParameter("date","2011/2/2");
        ServletRequestParameterPropertyValues propertyValues = new ServletRequestParameterPropertyValues(request);
        //也可以使用此方式进行数据绑定类型转换
//        propertyValues.add("name", 34);
//        propertyValues.add("age", "12");
        dataBinder.bind(propertyValues);
        System.out.println(s22Bean2);
基本的类型转换与数据绑定用法
  • SimpleTypeConverter
  • BeanWrapperImpl
  • DirectFieldAccessor
  • ServletRequestDataBinder

数据绑定工厂

点击查看代码

ServletRequestDataBinderFactory 的用法和扩展点
  1. 可以解析控制器的 @InitBinder 标注方法作为扩展点,添加自定义转换器
    • 控制器私有范围
  2. 可以通过 ConfigurableWebBindingInitializer 配置 ConversionService 作为扩展点,添加自定义转换器
    • 公共范围
  3. 同时加了 @InitBinder 和 ConversionService 的转换优先级
    1. 优先采用 @InitBinder 的转换器
    2. 其次使用 ConversionService 的转换器
    3. 使用认转换器
    4. 特殊处理(例如有参构造)

获取泛型参数

点击查看代码

1. java api 获取泛型参数 2. spring api 获取泛型参数

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐