-
-
- 三类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); }
总结
- PropertyEditor用于字符串到其它对象的转换,由于其局限性,spring提供了converter接口,由ConversionService来调用对外提供服务,而TypeConverter综合了上述两种转换方式,交由TypeConverterDelegate来进行转换。
- TypeConverterDelegater先使用PropertyEditor转换器器转换,如果没找到对应的转换器器,会⽤ConversionService来进⾏行行对象转换。