所有相关接口的uml图:
一、spring中类型转换里面我开始看的时候觉得converter和formatter的功能很多疑问,先来分析这两个接口:
1、Converter.java
package org.springframework.core.convert.converter;
public interface Converter<S, T> {
T convert(S source);
}
2、Formatter.java
package org.springframework.format;
public interface Formatter<T> extends Printer<T>, Parser<T> {
}
从上面可以看出formatter时继承Printer、Parser接口
Printer.java
public interface Printer<T> {
String print(T fieldValue, Locale locale);
}
Parser.java
public interface Parser<T> {
T parse(String clientValue, Locale locale) throws ParseException;
}
首先coverter接口只有cover方法,两个不同类型之间的互转都是使用相同方法名称的方法。Formatter将cover方法拆成print和parse两个方法,两个方法对于往返多了中间变量String,也就是Formatter是Converter功能的子集。官方文档描述Coverter接口是提供通用类型转换,Formatter接口传递参数时多Locale属性而且两个方法于往返多了中间变量String,也就是可以根据用户的语言喜好对结果产生影响并且之间的传输通常使用String(这儿多理解一下),所以这样设计两个方法,Formatter大多数在货币(number)和日期上面使用。
二、看ConversionService接口的作用
ConversionService.java
package org.springframework.core.convert;
public interface ConversionService {
boolean canConvert(Class<?> sourceType, Class<?> targetType);
<T> T convert(Object source, Class<T> targetType);
boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);
Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}
ConversionService提供了和Converter.java相同方法名称的方法,但是方法参数不同,并且有两个,为什么有两个,因为这个时service,实现里面保存许多Converter的实现类的实例对象,通过这两个参数查找我们需要的Converter对象。另外提供测试需要的convert是否存在的两个canConvert方法。
三、ConverterRegistry的作用
ConverterRegistry.java
package org.springframework.core.convert.converter;
public interface ConverterRegistry {
void addConverter(Converter<?, ?> converter);
<S, T> void addConverter(Class<S> sourceType, Class<T> targetType, Converter<? super S, ? extends T> converter);
void addConverter(GenericConverter converter);
void addConverterFactory(ConverterFactory<?, ?> factory);
void removeConvertible(Class<?> sourceType, Class<?> targetType);
}
ConverterRegistry提供对Converter实现类的对象的注册和删除。
四、FormatterRegistry的作用
FormatterRegistry.java
package org.springframework.format;
public interface FormatterRegistry extends ConverterRegistry {
void addFormatterForFieldType(Class<?> fieldType, Printer<?> printer, Parser<?> parser);
void addFormatterForFieldType(Class<?> fieldType, Formatter<?> formatter);
void addFormatterForFieldType(Formatter<?> formatter);
void addFormatterForAnnotation(AnnotationFormatterFactory<?, ?> factory);
}
FormatterRegistry提供formatter注册converter,它的key是ConvertiblePair对象。ConvertiblePair是fieldType的绑定的往返对。
ConvertiblePair相关代码在GenericConverter.java中:
package org.springframework.core.convert.converter;
import java.util.Set;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
public interface GenericConverter {
@Nullable
Set<ConvertiblePair> getConvertibleTypes();
@Nullable
Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
final class ConvertiblePair {
private final Class<?> sourceType;
private final Class<?> targetType;
public ConvertiblePair(Class<?> sourceType, Class<?> targetType) {
Assert.notNull(sourceType, "Source type must not be null");
Assert.notNull(targetType, "Target type must not be null");
this.sourceType = sourceType;
this.targetType = targetType;
}
public Class<?> getSourceType() {
return this.sourceType;
}
public Class<?> getTargetType() {
return this.targetType;
}
@Override
public boolean equals(@Nullable Object other) {
if (this == other) {
return true;
}
if (other == null || other.getClass() != ConvertiblePair.class) {
return false;
}
ConvertiblePair otherPair = (ConvertiblePair) other;
return (this.sourceType == otherPair.sourceType && this.targetType == otherPair.targetType);
}
@Override
public int hashCode() {
return (this.sourceType.hashCode() * 31 + this.targetType.hashCode());
}
@Override
public String toString() {
return (this.sourceType.getName() + " -> " + this.targetType.getName());
}
}
}
五、FormatterRegistrar的作用:
FormatterRegistrar.java
package org.springframework.format;
public interface FormatterRegistrar {
void registerFormatters(FormatterRegistry registry);
}
在FormatterRegistrar
为给定格式类别注册多个相关转换器和格式化程序时非常有用,例如日期格式(日期格式互相转换有多个)。相关例子看DateFormatterRegistrar.java
六、Converter特有的接口
ConverterFactory.java
package org.springframework.core.convert.converter;
public interface ConverterFactory<S, R> {
<T extends R> Converter<S, T> getConverter(Class<T> targetType);
}
主要对Converter进行工厂模式包装,生成Converter实例对象。
GenericConverter.java
package org.springframework.core.convert.converter;
public interface GenericConverter {
public Set<ConvertiblePair> getConvertibleTypes();
Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}
该接口是对Converter接口的复杂情况使用的接口,其中多了getConvertibleTypes方法,获取source和target两个往返Field对应所有的Set<ConvertiblePair>,单个ConvertiblePair在ConversionService中是key,通过这个寻找需要的converter。
ConditionalConverter.java
public interface ConditionalConverter {
boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
}
有时,Converter
只有在特定条件成立时才需要运行,那么就需要使用这个接口的matches方法。那么就有了
ConditionalGenericConverter.java
public interface ConditionalGenericConverter extends GenericConverter, ConditionalConverter {
}
七、Formatter的其它接口
AnnotationFormatterFactory.java
package org.springframework.format;
public interface AnnotationFormatterFactory<A extends Annotation> {
Set<Class<?>> getFieldTypes();
Printer<?> getPrinter(A annotation, Class<?> fieldType);
Parser<?> getParser(A annotation, Class<?> fieldType);
}
ps:以上就是spring中“类型转换”提供的所有常用接口。spring中也有例子,下篇继续。如果无法理解,可以常看spring官方文档如果有错误,欢迎指出。