后端——框架——容器框架——spring_core——《官网》阅读笔记——第三章节2(转换器)

  转换器的知识大致可以分为两个部分

  1. 第一部分介绍将配置信息转换为bean对象或bean属性的类型。Spring大部分的配置信息都是字符串
  2. 第二部分介绍任意的类型转换,将A--->B,A,B都可以是任意的类型。

1、Str2Obj

  Str2Obj的意思是指String to Object。Spring将配置信息转换为bean对象或者bean属性类型至少需要两个步骤

  1. 将字符串转换为属性或对象需要的类型。
  2. 如果是属性,调用对象的setXX方法。

  负责第一步的接口为PropertyEditor,负责调用set方法的接口是BeanWrapper。

1.1  PropertyEditor

  PropertyEditor接口的职责是将字符串转换为正确的对象类型。

  PropertyEditor接口有很多实现类,spring有许多内置的XXEditor,它们大部分都在org.springframework.beans.propertyeditors。例如最为常见的CustomBooleanEditor,将字符串转换为布尔;CustomDateEditor,将字符串转换为日期。我们也可以自定义XXEditor,实现将字符串转换为自定义类型。

  要使PropertyEditor接口实现类生效,需要实现两个步骤:

  1. 第一步编写PropertyEditor的实现类,或者使用spring框架内置的实现类。
  2. 第二步注册PropertyEditor的实现类。

  第一步较为简单,如果要使用内置的PropertyEditor实现类,参考3.3.2的内容。

  注册PropertyEditor实现类的方式有三种:

  1. 第一种直接将XXPropertyEditor与XX对象放置在同一个包下,例如User类,直接将UserPropertyEditor放置到相同包下即可。
  2. 第二种配置CustomEditorConfigurer的customEditors属性
<!-- 注入customEditorConfigurer, 并配置customEditors属性   -->
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
	<!-- 该属性是Map对象,其中key值为转换的对象类型,value值为PropertyEditor接口的实现类 -->
	<property name="customEditors">
		<map>
			<!-- User类为自定义对象,UserPropertyEditor为自定义PropertyEditor接口实现类 -->
			<entry key="com.bean.User" value="com.propertyEditor.UserPropertyEditor"/>
		</map>
	</property>
</bean>

  3.第三种通过实现PropertyEditorRegistrar接口,并将实现类添加到customPropertyEditorRegistrar属性中。

  第一步,编写自定义实现类,实现register方法

/**
 * 
  * @Title: UserPropertyEditorRegistrar.java  
  * @Package com.propertyEditor  
  * @Description: UserPropertyEditor的注册器
  * @version V1.0
 */
public class UserPropertyEditorRegistrar implements PropertyEditorRegistrar {

	public void registerCustomEditors(PropertyEditorRegistry registry) {
		// 第一个参数为对象的类型,这里是User.class,第二个参数为UserPropertyEditor的实例
		registry.registerCustomEditor(User.class, new UserPropertyEditor());
	}
}

  第二步,配置CustomEditorConfigurer的propertyEditorRegistrars属性。

<!-- 注入XXPropertyRegistrars -->
<bean id="userEditorRegistrar" class="com.propertyEditor.UserPropertyEditorRegistrar"/>

<!-- 注入customEditorConfigurer, 并配置customEditors属性   -->
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
	<!-- 配置propertyEditorRegistrars属性 -->
	<property name="propertyEditorRegistrars">
		<list>
			<ref bean="userEditorRegistrar">
		</list>
	</property>
</bean>

  第三步,在Controller类中获取XXPropertyRegistrars,在initBinder方法中调用registerCustomEditors。

public final class RegisterUserController {
	
	@Autowired
    private final PropertyEditorRegistrar customPropertyEditorRegistrar;

    public RegisterUserController(PropertyEditorRegistrar propertyEditorRegistrar) {
        this.customPropertyEditorRegistrar = propertyEditorRegistrar;
    }

    protected void initBinder(HttpServletRequest request,
            ServletRequestDataBinder binder) throws Exception {
         // 这一步是关键
        this.customPropertyEditorRegistrar.registerCustomEditors(binder);
    }
}

  可以看到第三种注册方式非常繁琐,第一种虽然简单,但是有时候却并不想PropertyEditor放在实体类的包下,spring框架也是将所有的propertyEditor实现类单独放在一个包下,综合比较,第二种方式最优。

1.2  BeanWrapper

  通过BeanWrapper设置对象的某个属性,下例中有两种设置User的name属性的方式。

BeanWrapper user = new BeanWrapperImpl(new User());
// 设置user的名称
user.setPropertyValue("name", "张三");
// 第二种方式,通过创建PropertyValue对象设置user的名称
PropertyValue value = new PropertyValue("name", "张三");
user.setPropertyValue(value);

2、Obj2Obj

  对象与对象之间的转换有很多种实现方式,spring框架只是其中的一种方式。对象转对象大致可以归为三类:

  1. 单个对象转换为单个对象
  2. 单个对象转换为类体系结构,例如String转换为Enum。
  3. 集合相互转换,例如List<String>转换为List<Integer>。

2.1  Single2Single

  单个对象转换为单个对象有两个步骤:

  1. 第一步实现Convert接口,它只有一个方法convert,参数代表source,方法的返回值为target。
  2. 第二步注册XXConvert。

  注册XXConvert的方式为配置ConversionServiceFactoryBean的converters属性。

<!-- 注入ConversionServiceFactoryBean -->
<bean 
id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
	<!-- 配置converters属性 -->
	<property name="converters">
		<set>
			<!-- 自己编写的convert接口实现类 -->
			<bean class="com.converts.XXConverter" />
		</set>
	</property>
</bean>

  之后就可以获取ConversionServiceFactoryBean的实例,并调用它的API实现转换的功能。

2.2   Single2ClassHierarchy

  单个对象转换为类体系结构有两个步骤:

  1. 第一步编写ConvertFactory接口的实现类,实现getConverter方法,其中参数代表类结构中具体的类型。返回值为Converter接口实现类,它实现具体的转换逻辑。
  2. 第二步,注册,方法同Converter。

  官网的原示例将String转换为具体的枚举类型,代码如下:

/**
 * 
  * @Title: StringToEnumConverterFactory.java  
  * @Package com.propertyEditor  
  * @Description: 这个类将String对象转换为具体的枚举类型 
  * @version V1.0
 */
final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {
	// 这个是ConvertFactory接口中的方法,它只是获取具体的Converter
    public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
        return new StringToEnumConverter(targetType);
    }
    
    // Converter接口的实现类,不必是内部类的形式
    private final class StringToEnumConverter<T extends Enum> implements Converter<String, T> {
        private Class<T> enumType;
        public StringToEnumConverter(Class<T> enumType) {
            this.enumType = enumType;
        }

        public T convert(String source) {
            return (T) Enum.valueOf(this.enumType, source.trim());
        }
    }
}

2.3   Coll2Coll

  多个对象转换为多个对象的步骤和之前类似,区别在于实现GenericConvert接口。待补充。

       注:Spring还提供了ConversionService,它只是整合之前三种接口的功能,应用到了门面模式,步骤和注册方式和之前三种情形基本没什么区别

原文地址:https://www.cnblogs.com/rain144576/p/12272440.html