第二章 二节spring-core之converter深刻解读

前言

本章节深刻讲解spring的converter使用与细节,帮助你们在项目里面正确使用converter。converters是在项目开发里面比较实用,切便利的功能,可是在复杂的业务中,须要架构师或者架构组设计,实现整套规范。源码解读没法经过文字很详细的解释,诠释。须要读者屡次阅读,深刻理解,组织逻辑,大脑慢慢造成整个流程。java

converter类关系体系

输入图片说明

从类实例图中,能够观察到整个converter类关系体系分为两大块。spring

  • 操做体系
  • 管理体系

操做体系

Converter
public interface Converter<S, T> {
	T convert(S source);
}
ConverterFactory
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缓存

GenericConverter
public interface GenericConverter {

	Set<ConvertiblePair> getConvertibleTypes();

	Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}
ConditionalConverter
public interface ConditionalConverter {
	boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
}
public interface ConditionalGenericConverter extends GenericConverter, ConditionalConverter {

}

先提早告诉你们架构

  • 管理体系直接调用 GenericConverter 的子类,而后GenericConverter的子类进行转换,好比直接进行转换,也能够经过调用Converter与ConverterFactory的方法进行转换。
  • 每次获得GenericConverter,都会调用ConditionalConverter的matches 执行判断是否达到条件,条件到达就会获得当前对象 这是一个很奇怪,很是难以理解的设计。可是这个设计最重要的目的是为了统一Converter与ConverterFactory的行为,让其保存一致。若是让其保持一致的请看GenericConverter实现类ConverterFactoryAdapter与ConverterAdapter。还有这个设计是 保证可扩展性。

管理体系

输入图片说明

ConverterRegistry
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

ConversionService
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

ConfigurableConversionService
public interface ConfigurableConversionService extends ConversionService, ConverterRegistry {

}

嗯,ConfigurableConversionService就是摆看的,主要用于统一ConversionService与ConverterRegistry接口,方便实现类的操做this

GenericConversionService
public class GenericConversionService implements ConfigurableConversionService {
}

从class声明中,能够得知GenericConversionService实现了ConversionService和ConverterRegistry全部方法设计

先看GenericConversionService非继承与实现的方法
/**
   *若是目标类型是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"));
	}
}
ConversionService实现
@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

  • 第一步是获得原类型与目标类型,
  • 第二步调用getConverter方法,
  • 第三步处理的逻辑
注意
  1. NO_OP_CONVERTER 与 NO_MATCH 是不一样的实例,可是行为是同样的。convert直接返回原数据
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;
	}
	}
}
ConverterRegistry实现内容
@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实现内容 很是简单对象

  • 第一步是获得原类型与目标类型,
  • 第二步 把对象转换器与原类型,目标类型封装成对应的GenericConverter不一样子接口
  • 第三步 加入converters
  • 第四部 清空缓存
DefaultConversionService

DefaultConversionService注册了不少通用Converter,到ConversionService里面,这些通用的ConversionService,很好用。为了让博客有更多的可读性,这里不贴源代码。若是你们有意愿能够去看看。

converters核心子体系

ConvertiblePairs

ConvertiblePair是一个简单的实体类,重写hashCode,equals,toString方法,做为某个Converters.converters的key

final class ConvertiblePair {

	private final Class<?> sourceType;

	private final Class<?> targetType;
}
ConvertersForPair
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);
add操做
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;
}
find操做
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;
}

总结

  1. 类依赖关系分为:操做体系与管理体系
  2. converter的ConvertersForPair类解决了接口多实现也类多子类的识别关系,是整个体系中最难理解的。
  3. 管理体系直接调用 GenericConverter 的子类,而后GenericConverter的子类进行转换,好比直接进行转换,也能够经过调用Converter与ConverterFactory的方法进行转换
  4. 每次获得GenericConverter,都会调用ConditionalConverter的matches 执行判断是否达到条件,条件到达就会获得当前对象
  5. add时候转换器会存储Converters类里面, 6,Converters分 globalConverters与converters
    1. 添加 globalConverters的条件是
      1. converter.getConvertibleTypes()返回未null
      2. converter同时实现了ConditionalConverter
    2. 没有添加到globalConverters添加到converters中
  6. 每次添加删除都会清空GenericConversionService.converterCache缓存。原理请送第二点总结分析
  7. 当getConverters时,先识别GenericConversionService.converterCache是否存在,若是不存在从converters找

使用的模式

单例模式

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);
}
相关文章
相关标签/搜索