本章节深刻讲解spring的converter使用与细节,帮助你们在项目里面正确使用converter。converters是在项目开发里面比较实用,切便利的功能,可是在复杂的业务中,须要架构师或者架构组设计,实现整套规范。源码解读没法经过文字很详细的解释,诠释。须要读者屡次阅读,深刻理解,组织逻辑,大脑慢慢造成整个流程。java
从类实例图中,能够观察到整个converter类关系体系分为两大块。spring
public interface Converter<S, T> { T convert(S source); }
public interface ConverterFactory<S, R> { <T extends R> Converter<S, T> getConverter(Class<T> targetType); }
两个很是简单的类,Converter的子类是负责实现转换,那ConverterFactory是用来干什么。 好比 有一个需求须要把数字型转成字符串类型,可是Number的子类有Byte,Short,Integer,Long等等十多个,每一个有一个Converter实现(必须每一个都一个Converter,不然代码很是很差管理,经过方法实现十分不优雅),这么多如何进行管理。spring提供了一个解决方法经过工厂模式即便用ConverterFactory管理全部Converter缓存
public interface GenericConverter { Set<ConvertiblePair> getConvertibleTypes(); Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType); }
public interface ConditionalConverter { boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType); }
public interface ConditionalGenericConverter extends GenericConverter, ConditionalConverter { }
先提早告诉你们架构
public interface ConverterRegistry { void addConverter(Converter<?, ?> converter); void addConverter(Class<?> sourceType, Class<?> targetType, Converter<?, ?> converter); void addConverter(GenericConverter converter); void addConverterFactory(ConverterFactory<?, ?> converterFactory); void removeConvertible(Class<?> sourceType, Class<?> targetType); }
从声明的方法能够看出ConverterRegistry负责converter的添加与删除ide
public interface ConversionService { boolean canConvert(Class<?> sourceType, Class<?> targetType); boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType); <T> T convert(Object source, Class<T> targetType); Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType); }
声明的方法能够看出ConversionService负责converter执行与是否有对应类型的converterui
public interface ConfigurableConversionService extends ConversionService, ConverterRegistry { }
嗯,ConfigurableConversionService就是摆看的,主要用于统一ConversionService与ConverterRegistry接口,方便实现类的操做this
public class GenericConversionService implements ConfigurableConversionService { }
从class声明中,能够得知GenericConversionService实现了ConversionService和ConverterRegistry全部方法设计
/** *若是目标类型是Optional,那么返回一个空Optional **/ protected Object convertNullSource(TypeDescriptor sourceType, TypeDescriptor targetType) { if (javaUtilOptionalEmpty != null && targetType.getObjectType() == javaUtilOptionalEmpty.getClass()) { return javaUtilOptionalEmpty; } return null; } protected GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) { // 建立 ConverterCacheKey 对象,做为map的key,从converterCache获得converter对象 ConverterCacheKey key = new ConverterCacheKey(sourceType, targetType); GenericConverter converter = this.converterCache.get(key); // 从缓存中获得的converter是否为null if (converter != null) { return (converter != NO_MATCH ? converter : null); } // 从converters 查询converter converter = this.converters.find(sourceType, targetType); // 查询结果为空 if (converter == null) { // 获得默认的 Converter converter = getDefaultConverter(sourceType, targetType); } //若是不等于空 把converter 加入缓存中 if (converter != null) { this.converterCache.put(key, converter); return converter; } // 若是等于空,对应的操做的value是NO_MATCH this.converterCache.put(key, NO_MATCH); return null; } /** * 你们十分会很奇怪,已经有多个默认Converter的,为何不值直接this.converterCache.put(key, NO_MATCH), * 还经过getDefaultConverter方法在获得一个默认的Converter。 * GenericConversionService的getDefaultConverter会返回一个默认的NO_OP_CONVERTER, * GenericConversionService的子类能够经过重写getDefaultConverter方法获得子类想提供的DefaultConverter, * getDefaultConverter的存在提供了灵活的扩展 **/ protected GenericConverter getDefaultConverter(TypeDescriptor sourceType, TypeDescriptor targetType) { // sourceType.isAssignableTo(targetType) 用于判断类型与泛型都一致,若是一致就返回NO_OP_CONVERTER // NO_OP_CONVERTER的convert方法会直接方法传递的原数据(PS,点) return (sourceType.isAssignableTo(targetType) ? NO_OP_CONVERTER : null); } /** * 获得converter实参的泛型, * ConverterFactory<S, R> 与 Converter<S, T> 第一个泛型(S)是原类型,第二个泛型(R与T)是目标类型 **/ private ResolvableType[] getRequiredTypeInfo(Object converter, Class<?> genericIfc) { ResolvableType resolvableType = ResolvableType.forClass(converter.getClass()).as(genericIfc); ResolvableType[] generics = resolvableType.getGenerics(); if (generics.length < 2) { return null; } Class<?> sourceType = generics[0].resolve(); Class<?> targetType = generics[1].resolve(); if (sourceType == null || targetType == null) { return null; } return generics; } private void invalidateCache() { this.converterCache.clear(); } private Object handleConverterNotFound(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { assertNotPrimitiveTargetType(sourceType, targetType); return null; } // 若是目标类型与原类型一致,就直接方法原数据 if (sourceType.isAssignableTo(targetType) && targetType.getObjectType().isInstance(source)) { return source; } throw new ConverterNotFoundException(sourceType, targetType); } private Object handleResult(TypeDescriptor sourceType, TypeDescriptor targetType, Object result) { if (result == null) { assertNotPrimitiveTargetType(sourceType, targetType); } return result; } private void assertNotPrimitiveTargetType(TypeDescriptor sourceType, TypeDescriptor targetType) { if (targetType.isPrimitive()) {// 目标类型是基本类型或者包装类型,就抛出异常。缘由未知 throw new ConversionFailedException(sourceType, targetType, null, new IllegalArgumentException("A null value cannot be assigned to a primitive type")); } }
@Override public boolean canConvert(Class<?> sourceType, Class<?> targetType) { Assert.notNull(targetType, "targetType to convert to cannot be null"); return canConvert((sourceType != null ? TypeDescriptor.valueOf(sourceType) : null), TypeDescriptor.valueOf(targetType)); } @Override public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) { Assert.notNull(targetType, "targetType to convert to cannot be null"); if (sourceType == null) { return true; } GenericConverter converter = getConverter(sourceType, targetType); return (converter != null); } // 用来识别,原类型与目标类型的converter是不是NO_OP_CONVERTER public boolean canBypassConvert(TypeDescriptor sourceType, TypeDescriptor targetType) { Assert.notNull(targetType, "targetType to convert to cannot be null"); if (sourceType == null) { return true; } GenericConverter converter = getConverter(sourceType, targetType); return (converter == NO_OP_CONVERTER); } @Override @SuppressWarnings("unchecked") public <T> T convert(Object source, Class<T> targetType) { Assert.notNull(targetType, "targetType to convert to cannot be null"); return (T) convert(source, TypeDescriptor.forObject(source), TypeDescriptor.valueOf(targetType)); } @Override public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { Assert.notNull(targetType, "targetType to convert to cannot be null"); if (sourceType == null) {// 判断原类型值是否为空 Assert.isTrue(source == null, "source must be [null] if sourceType == [null]"); return handleResult(null, targetType, convertNullSource(null, targetType)); } if (source != null && !sourceType.getObjectType().isInstance(source)) {// 判断原数据的类型与原类型是否相等,不相等就没法转换 throw new IllegalArgumentException("source to convert from must be an instance of " + sourceType + "; instead it was a " + source.getClass().getName()); } GenericConverter converter = getConverter(sourceType, targetType); if (converter != null) { // 执行converter // converter.converter(source, sourceType, targetType); 封装了下代码,里面处理了异常 // 异常,是返回null // converter.converter(source, sourceType, targetType) 结果也多是也null, Object result = ConversionUtils.invokeConverter(converter, source, sourceType, targetType); return handleResult(sourceType, targetType, result); } return handleConverterNotFound(source, sourceType, targetType); } public Object convert(Object source, TypeDescriptor targetType) { return convert(source, TypeDescriptor.forObject(source), targetType); }
从实现能够分析到 全部方法code
public class GenericConversionService implements ConfigurableConversionService { private static final GenericConverter NO_OP_CONVERTER = new NoOpConverter("NO_OP"); private static final GenericConverter NO_MATCH = new NoOpConverter("NO_MATCH"); private static class NoOpConverter implements GenericConverter { private final String name; public NoOpConverter(String name) { this.name = name; } @Override public Set<ConvertiblePair> getConvertibleTypes() { return null; } @Override public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { return source; } @Override public String toString() { return this.name; } } }
@Override public void addConverter(Converter<?, ?> converter) { ResolvableType[] typeInfo = getRequiredTypeInfo(converter, Converter.class); Assert.notNull(typeInfo, "Unable to the determine sourceType <S> and targetType " + "<T> which your Converter<S, T> converts between; declare these generic types."); addConverter(new ConverterAdapter(converter, typeInfo[0], typeInfo[1])); } @Override public void addConverter(Class<?> sourceType, Class<?> targetType, Converter<?, ?> converter) { addConverter(new ConverterAdapter(converter,ResolvableType.forClass(sourceType), ResolvableType.forClass(targetType))); } @Override public void addConverter(GenericConverter converter) { this.converters.add(converter); invalidateCache(); } @Override public void addConverterFactory(ConverterFactory<?, ?> converterFactory) { ResolvableType[] typeInfo = getRequiredTypeInfo(converterFactory, ConverterFactory.class); Assert.notNull(typeInfo, "Unable to the determine source type <S> and target range type R which your " + "ConverterFactory<S, R> converts between; declare these generic types."); addConverter(new ConverterFactoryAdapter(converterFactory,new ConvertiblePair(typeInfo[0].resolve(), typeInfo[1].resolve()))); } @Override public void removeConvertible(Class<?> sourceType, Class<?> targetType) { this.converters.remove(sourceType, targetType); invalidateCache(); }
ConverterRegistry实现内容 很是简单对象
DefaultConversionService注册了不少通用Converter,到ConversionService里面,这些通用的ConversionService,很好用。为了让博客有更多的可读性,这里不贴源代码。若是你们有意愿能够去看看。
ConvertiblePair是一个简单的实体类,重写hashCode,equals,toString方法,做为某个Converters.converters的key
final class ConvertiblePair { private final Class<?> sourceType; private final Class<?> targetType; }
private static class ConvertersForPair { private final LinkedList<GenericConverter> converters = new LinkedList<GenericConverter>(); public void add(GenericConverter converter) { this.converters.addFirst(converter); } public GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) { for (GenericConverter converter : this.converters) { if (!(converter instanceof ConditionalGenericConverter) || ((ConditionalGenericConverter) converter).matches(sourceType, targetType)) { return converter; } } return null; } @Override public String toString() { return StringUtils.collectionToCommaDelimitedString(this.converters); } }
ConvertersForPair 是一个比较难理解的类。ConvertersForPair存在是作什么的?
ConvertersForPai是当作map的value存入map,那么这个map的key,是原对象与目标对象的封装对象ConvertiblePair。那么ConvertiblePair 对应一个ConvertersForPair。若是一个ConvertersForPair对应两个GenericConverter,你们会想怎么这么可能出现一个ConvertersForPair对应两个GenericConverter。那么你们想象,若是对象与目标对象都是接口或者对象与目标对象都有多个子类怎么办?
好比 原对象是A类,, 目标对象是E类,。A类有子类B,C,D ,E类 有F,G,H,如今建立一个AEGenericConverter的GenericConverter实现觉接之间转换问题。随着时间的发展,其余模块有了A的子类AB,AC,AD。这个时候AEGenericConverter,就没法作到。必须须要新的AAEGenericConverter,同时把A转换E。这个须要目前是这个体系里面对复杂的需求了。
private final Set<GenericConverter> globalConverters = new LinkedHashSet<GenericConverter>(); private final Map<ConvertiblePair, ConvertersForPair> converters = new LinkedHashMap<ConvertiblePair, ConvertersForPair>(36);
public void add(GenericConverter converter) { // 调用GenericConverter.getConvertibleTypes方法获得Set<ConvertiblePair>,详细分析请看ConditionalGenericConverter 解读 // 一个转换器能够把多个类型转换成多个类型 Set<ConvertiblePair> convertibleTypes = converter.getConvertibleTypes(); if (convertibleTypes == null) { // 当convertibleTypes 为null的时候,就出现一个问题,怎么知道这个GenericConverter把什么转成什么, // 那么须要converter 实现了ConditionalConverter的matches方法,进行识别是否能够转换 Assert.state(converter instanceof ConditionalConverter,"Only conditional converters may return null convertible types"); //加入全局Converters this.globalConverters.add(converter); }else { // 一个转换器能够把多个类型转换成多个类型, 为何出现,请看ConvertersForPair 出现的缘由 for (ConvertiblePair convertiblePair : convertibleTypes) { // 经过ConvertiblePair 找到 ConvertersForPair ConvertersForPair convertersForPair = getMatchableConverters(convertiblePair); convertersForPair.add(converter); } } } private ConvertersForPair getMatchableConverters(ConvertiblePair convertiblePair) { // 经过convertiblePair 从缓存获得ConvertersForPair ConvertersForPair convertersForPair = this.converters.get(convertiblePair); if (convertersForPair == null) { // 若是缓存中没有,建立一个ConvertersForPair并加入缓存中。 convertersForPair = new ConvertersForPair(); this.converters.put(convertiblePair, convertersForPair); } return convertersForPair; }
public GenericConverter find(TypeDescriptor sourceType, TypeDescriptor targetType) { // 搜索完整类型层次结构, 为何出现,请看ConvertersForPair 出现的缘由 List<Class<?>> sourceCandidates = getClassHierarchy(sourceType.getType()); List<Class<?>> targetCandidates = getClassHierarchy(targetType.getType()); for (Class<?> sourceCandidate : sourceCandidates) { for (Class<?> targetCandidate : targetCandidates) { // 封装一个ConvertiblePair 对象做为 key ConvertiblePair convertiblePair = new ConvertiblePair(sourceCandidate, targetCandidate); // 去缓存里面查询GenericConverter GenericConverter converter = getRegisteredConverter(sourceType, targetType, convertiblePair); if (converter != null) { return converter; } } } return null; } private GenericConverter getRegisteredConverter(TypeDescriptor sourceType,TypeDescriptor targetType, ConvertiblePair convertiblePair) { // 若是在converters与globalConverters,都有一个ByteBuffer 转 Array。在执行的时候,会选择匹配converters。 // 检查特定注册转换器 ConvertersForPair convertersForPair = this.converters.get(convertiblePair); if (convertersForPair != null) { GenericConverter converter = convertersForPair.getConverter(sourceType, targetType); if (converter != null) { return converter; } } // 检查动态匹配的条件转换器 for (GenericConverter globalConverter : this.globalConverters) { if (((ConditionalConverter) globalConverter).matches(sourceType, targetType)) { return globalConverter; } } return null; }
DefaultConversionService使用了单例模式
private static volatile DefaultConversionService sharedInstance; public static ConversionService getSharedInstance() { if (sharedInstance == null) { synchronized (DefaultConversionService.class) { if (sharedInstance == null) { sharedInstance = new DefaultConversionService(); } } } return sharedInstance; }
public interface ConverterFactory<S, R> { <T extends R> Converter<S, T> getConverter(Class<T> targetType); }