天天看点

Spring源码:Converter及TypeConverter类解析

      • 三类Converter接口
      • TyperConverter
      • PropertyEditor
      • 总结

三类Converter接口

Spring提供了3种converter接口,分别是Converter、ConverterFactory和GenericConverter.一般用于1:1, 1:N, N:N的source->target类型转化。

  • Converter接口
    public interface Converter<S, T> {
      // 将S转换成T
    T convert(S source);
    }
               
  • GenericConverter接口:用于在两种或更多种类型之间转换的通用转换器接口。
    public interface GenericConverter {
    
    Set<ConvertiblePair> getConvertibleTypes();
    
    Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
    
    /**
     * Holder for a source-to-target class pair.
     */
    final class ConvertiblePair {
        private final Class<?> sourceType;
        private final Class<?> targetType;
    }
    }
               
  • ConverterFactory接口:
    public interface ConverterFactory<S, R> {
    
    /**
     * Get the converter to convert from S to target type T, where T is also an instance of R.
     */
    <T extends R> Converter<S, T> getConverter(Class<T> targetType);
    
    }
               

TyperConverter

  • TypeConverter接口
    /**
     * 定义类型转换方法的接口。通常(但不一定)与PropertyEditorRegistry接口一起实现
     * 通常接口TypeConverter的实现是基于非线程安全的PropertyEditors类,因此也不是线程安全的
     */
    public interface TypeConverter {
    
        /**
         * 将参数中的value转换成requiredType类型
         * 从String到任何类型的转换通常使用PropertyEditor类的setAsText方法或ConversionService中的Spring Converter
         */
        <T> T convertIfNecessary(Object value, Class<T> requiredType) throws TypeMismatchException;
    
        /**
         * 意义同上,增加了作为转换目标的方法参数,主要用于分析泛型类型,可能是null
         */
        <T> T convertIfNecessary(Object value, Class<T> requiredType, MethodParameter methodParam) throws TypeMismatchException;
    
        /**
         * 意义同上,增加了转换目标的反射field
         */
        <T> T convertIfNecessary(Object value, Class<T> requiredType, Field field) throws TypeMismatchException;
    }
               
  • TypeConverterSupport抽象类:TypeConverter的基本实现类,同时也是BeanWrapperImpl类的依赖类。
    public abstract class TypeConverterSupport extends PropertyEditorRegistrySupport implements TypeConverter {
      // 委托给TypeConverterDelegate来转换
    TypeConverterDelegate typeConverterDelegate;
    
    @Override
    public <T> T convertIfNecessary(Object value, Class<T> requiredType) throws TypeMismatchException {
        return doConvert(value, requiredType, null, null);
    }
    
    @Override
    public <T> T convertIfNecessary(Object value, Class<T> requiredType, MethodParameter methodParam) throws TypeMismatchException {
        return doConvert(value, requiredType, methodParam, null);
    }
    
    @Override
    public <T> T convertIfNecessary(Object value, Class<T> requiredType, Field field) throws TypeMismatchException {
        return doConvert(value, requiredType, null, field);
    }
    
    private <T> T doConvert(Object value, Class<T> requiredType, MethodParameter methodParam, Field field) throws TypeMismatchException {
          if (field != null) {
              return this.typeConverterDelegate.convertIfNecessary(value, requiredType, field);
            } else {
              return this.typeConverterDelegate.convertIfNecessary(value, requiredType, methodParam);
            }
    }
    
    }
               
  • TypeConverterDelegate类:类型转换的委托类,所有类型转换的工作都由该类完成,即将属性转换为其他类型的Spring内部使用方法(内部实现: 先使用PropertyEditor转换器器转换,如果没找到对应的转换器器,会⽤ConversionService来进⾏行行对象转换。)
    class TypeConverterDelegate {
        private final PropertyEditorRegistrySupport propertyEditorRegistry;
        private final Object targetObject;
        // ......
    }
               
  • SimpleTypeConverter源代码
    /**不在特定目标对象上运行的TypeConverter接口的简单实现。这是使用完整的BeanWrapperImpl实例来实现任意类型转换需求的替代方法,同时使用相同的转换算法(包括委托给PropertyEditor和ConversionService)。
     */
    public class SimpleTypeConverter extends TypeConverterSupport {
    
        public SimpleTypeConverter() {
            this.typeConverterDelegate = new TypeConverterDelegate(this);
            registerDefaultEditors();
        }
    }
               

PropertyEditor

  • PropertyEditor接口(jdk):用于字符串到其它对象的转换,PropertyEditor是遵循javaBean规范的属性处理器,其通过set方法设置属性值,通过get方法获取属性值,相应的转换逻辑就隐藏于其中。
  • **PropertyEditorSupport类(jdk):**PropertyEditor接口的默认实现。
    编写自己的PropertyEditor,通常是继承PropertyEditorSupport,而不用实现PropertyEditor,这样就不用重写PropertyEditor的所有方法了。
  • PropertyEditorRegistry接口: 封装用于注册JavaBeans PropertyEditors的方法。这是PropertyEditorRegistrar操作的中央接口。

    内部提供了三个函数用于PropertyEditor的注册和查找

    public interface PropertyEditorRegistry {
    
      void registerCustomEditor(Class<?> requiredType, PropertyEditor propertyEditor);
    
      /**每个属性路径只支持一个已注册的自定义编辑器。对于集合/数组,不要同时为集合/数组和相同属性上的每个元素注册一个编辑器。例如,如果您想为“items[n].quantity”注册一个编辑器(对于所有值n),您应该使用“items.quantity”作为这个方法“propertyPath”参数的值。**/
      // propertyPath:属性的路径(名称或嵌套路径),如果为给定类型的所有属性注册一个编辑器,则为null
    void registerCustomEditor(Class<?> requiredType, String propertyPath, PropertyEditor propertyEditor);
    
    PropertyEditor findCustomEditor(Class<?> requiredType, String propertyPath);
    
    }
               
  • **PropertyEditorRegistrySupport类:**PropertyEditorRegistry接口的默认实现,并且提供了默认editors和自定义editors的管理,主要作为服务BeanWrapperImpl的基类。
    public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
      // ......
    private ConversionService conversionService;
    
    private boolean defaultEditorsActive = false;
    
    private boolean configValueEditorsActive = false;
    
    private Map<Class<?>, PropertyEditor> defaultEditors;
    
    private Map<Class<?>, PropertyEditor> overriddenDefaultEditors;
    
    private Map<Class<?>, PropertyEditor> customEditors;
    
    private Map<String, CustomEditorHolder> customEditorsForPath;
      // ......
    }
               
  • CustomEditorConfigurer类:该类是BeanFactoryPostProcessor(BFPP类)的实现者,该类允许自定义属性编辑器的方便注册。常用注册方式:
    <!--方式一-->
    <bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
     <property name="propertyEditorRegistrars">
       <list>
         <bean class="mypackage.MyCustomDateEditorRegistrar"/>
         <bean class="mypackage.MyObjectEditorRegistrar"/>
       </list>
     </property>
    </bean>
    
    <!--方式二-->
    <bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
     <property name="customEditors">
       <map>
         <entry key="java.util.Date" value="mypackage.MyCustomDateEditor"/>
         <entry key="mypackage.MyObject" value="mypackage.MyObjectEditor"/>
       </map>
     </property>
    </bean>
               
  • PropertyEditorRegistrar接口:用于使用属性编辑器注册表注册自定义属性编辑器的策略的接口,当需要在几种不同的情况下使用同一组属性编辑器时,这一点特别有用:编写相应的注册器并在每种情况下重用它。
    public interface PropertyEditorRegistrar {
      // 该方法传入registry并添加自定义的PropertyEditor,一般情况下传入的registry是BeanWrapperImpl的实体,所以就等于将自定义的PropertyEditor注入到BeanWrapperImpl里面
    void registerCustomEditors(PropertyEditorRegistry registry);
    }
               

总结

  1. PropertyEditor用于字符串到其它对象的转换,由于其局限性,spring提供了converter接口,由ConversionService来调用对外提供服务,而TypeConverter综合了上述两种转换方式,交由TypeConverterDelegate来进行转换。
  2. TypeConverterDelegater先使用PropertyEditor转换器器转换,如果没找到对应的转换器器,会⽤ConversionService来进⾏行行对象转换。

继续阅读