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

前言

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

converter类关系体系

输入图片说明

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

  • 操作体系
  • 管理体系

操作体系

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的添加与删除

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执行与是否有对应类型的converter

ConfigurableConversionService
public interface ConfigurableConversionService extends ConversionService, ConverterRegistry {

}

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

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);
}

从实现可以分析到 所有方法

  • 第一步是得到原类型与目标类型,
  • 第二步调用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);
}

转载于:https://my.oschina.net/u/1261452/blog/1799439

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值