gpt4 book ai didi

Spring读源码系列番外篇---06----类型转换---下---ConversionService相关家族

转载 作者:知者 更新时间:2024-03-13 02:26:35 25 4
gpt4 key购买 nike

系列文章:

Spring读源码系列番外篇—01–PropertyValue相关类

Spring读源码系列番外篇—02—PropertyResolver的结构体系剖析—上

Spring读源码系列番外篇—03—PropertyResolver的结构体系剖析—下

Spring读源码系列番外篇—04----类型转换–上

Spring读源码系列番外篇—05----类型转换—中

引子

Spirng 3.0全新一代的类型转换机制,它提供的三种类型转换器(Converter、ConverterFactory、GenericConverter),分别可处理1:1、1:N、N:N的类型转换。

按照Spring的设计习惯,必有一个注册中心来统一管理,负责它们的注册、删除等,它就是ConverterRegistry。

另外,内建的绝大多数转换器访问权限都是default/private,那么如何使用它们,以及屏蔽各种转换器的差异化呢?为此,Spring提供了一个统一类型转换服务,它就是ConversionService。

新一代类型转换组件简介

ConverterRegistry和ConversionService的关系密不可分,前者为后者提供转换器管理支撑,后者面向使用者提供服务。本文涉及到的接口/类有:

  • ConverterRegistry:转换器注册中心。负责转换器的注册、删除
  • ConversionService:统一的类型转换服务。属于面向开发者使用的门面接口
  • ConfigurableConversionService:上两个接口的组合接口
  • GenericConversionService:上个接口的实现,实现了注册管理、转换服务的几乎所有功能,是个实现类而非抽象类
  • DefaultConversionService:继承自GenericConversionService,在其基础上注册了一批默认转换器(Spring内建),从而具备基础转换能力,能解决日常绝大部分场景

ConverterRegistry

public interface ConverterRegistry {
    //注册一个1:1的转换器----会尝试去参数化类型中提取sourceType和targetType
	void addConverter(Converter<?, ?> converter);

 //注册一个1:1的转换器----明确sourceType和targetType
	<S, T> void addConverter(Class<S> sourceType, Class<T> targetType, Converter<? super S, ? extends T> converter);

  //注册一个n:n的转换器
	void addConverter(GenericConverter converter);

//注册一个1:n的转化器
	void addConverterFactory(ConverterFactory<?, ?> factory);

//移除某个转换器
	void removeConvertible(Class<?> sourceType, Class<?> targetType);

}

ConverterRegistry有子接口FormatterRegistry,它属于格式化器的范畴.

ConversionService

面向使用者的统一类型转换服务。换句话说:站在使用层面,你只需要知道ConversionService接口API的使用方式即可,并不需要关心其内部实现机制,可谓对使用者非常友好。

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和ConverterRegistry的继承树殊途同归,都直接指向了ConfigurableConversionService这个分支,下面就对它进行介绍

ConfigurableConversionService

ConversionService和ConverterRegistry的组合接口,自己并未新增任何接口方法。

public interface ConfigurableConversionService extends ConversionService, ConverterRegistry {

}
插眼: ResolvableType

为什么要先提一嘴这个类呢?
当然是因为我们下面要将的GenericConversionService源码中大量使用到了这个类

该类作用很简单,我这里简单介绍一下,就不贴出源码了,毕竟方法挺多的:

  • 封装一个JAVA类型,提供对父类,接口和反向的访问已经最终解析为class的能力
  • ResolvableTypes 可以从字段、方法参数、方法返回或类中获得。此类中的大多数方法本身都会返回 ResolvableTypes,从而可以轻松导航
private HashMap<Integer, List<String>> myMap;
  
   public void example() {
       ResolvableType t = ResolvableType.forField(getClass().getDeclaredField("myMap"));
       t.getSuperType(); // AbstractMap<Integer, List<String>>
       t.asMap(); // Map<Integer, List<String>>
       t.getGeneric(0).resolve(); // Integer
       t.getGeneric(1).resolve(); // List
       t.getGeneric(1); // List<String>
       //第二个泛型,里面的泛型,即List<String>里面的String
       t.resolveGeneric(1, 0); // String
   }

通过上面这个简单案例应该可以让各位有个大概的了解,这就差不多了,那么我们进入正题吧

我觉得这个类,有空可以参考在自己项目中用用,毕竟算是一个比较方便的工具类

GenericConversionService

对ConfigurableConversionService接口提供了完整实现的实现类。换句话说:ConversionService和ConverterRegistry接口的功能均通过此类得到了实现,所以它是本文重点。

public class GenericConversionService implements ConfigurableConversionService {

	/**
	 * General NO-OP converter used when conversion is not required.
	 * 
	 */
	private static final GenericConverter NO_OP_CONVERTER = new NoOpConverter("NO_OP");

	/**
	 * Used as a cache entry when no converter is available.
	 * This converter is never returned.
	 */
	private static final GenericConverter NO_MATCH = new NoOpConverter("NO_MATCH");

    
    //Converters是GenericConversionService的内部类,用于管理(添加、删除、查找)转换器们。
    //也就说对ConverterRegistry接口的实现最终是委托给它去完成的,它是整个转换服务正常work的内核
	private final Converters converters = new Converters();
    
    //它用两个成员变量来管理转换器们,其中converterCache是缓存用于加速查找,因此更为重要的便是Converters喽。 
	private final Map<ConverterCacheKey, GenericConverter> converterCache = new ConcurrentReferenceHashMap<>(64);

	//-------------------------ConverterRegistry注册相关接口的具体实现------------------------
   
    //增加一个1:1的转化器
	@Override
	public void addConverter(Converter<?, ?> converter) {
	//getRequiredTypeInfo是一个工具方法,功能是返回传入converter的具体的泛型参数数组
	//泛型参数都被ResolvableType进行包裹,长度为2,一个是原对象类型,一个是目标对象类型
		ResolvableType[] typeInfo = getRequiredTypeInfo(converter.getClass(), Converter.class);
		//对代理进行判断---这个地方我暂时不清楚,等后面我懂了,就回来完善一下!!!
		if (typeInfo == null && converter instanceof DecoratingProxy) {
           //这套组合拳目的在于拿到泛型参数数组
			typeInfo = getRequiredTypeInfo(((DecoratingProxy) converter).getDecoratedClass(), Converter.class);
		}
		if (typeInfo == null) {
			throw new IllegalArgumentException("Unable to determine source type <S> and target type <T> for your " +
					"Converter [" + converter.getClass().getName() + "]; does the class parameterize those types?");
		}
		//添加转换器----将所有converter都通过ConverterAdapter转换为
		addConverter(new ConverterAdapter(converter, typeInfo[0], typeInfo[1]));
	}

//和上面那个重载方法相比,少了去解析出convert泛型参数的过程
	@Override
	public <S, T> void addConverter(Class<S> sourceType, Class<T> targetType, Converter<? super S, ? extends T> converter) {
	//这一步和上面那个重载方法一样---这里也用到了适配器模式和上面一样
		addConverter(new ConverterAdapter(
				converter, ResolvableType.forClass(sourceType), ResolvableType.forClass(targetType)));
	}

//上面两个重载方法最终调用的方法--这里参数需要的是GenericConverter
//因为我们之前说过有1:1,1:n,n:n三种转换器,因此我们这边把所有转换器都转换为通用的GenericConverter(n:n)进行管理
	@Override
	public void addConverter(GenericConverter converter) {
	//converters是一个内部类,它管理所有转换器,包括添加、删除、查找。
	//这个一会在细聊
		this.converters.add(converter);
		//清除缓存集合
		invalidateCache();
	}

//添加一个1:n的转换器
	@Override
	public void addConverterFactory(ConverterFactory<?, ?> factory) {
	   //同样因为转换器的泛型参数不确定,因此需要先解析出来
		ResolvableType[] typeInfo = getRequiredTypeInfo(factory.getClass(), ConverterFactory.class);
		//处理代理问题
		if (typeInfo == null && factory instanceof DecoratingProxy) {
			typeInfo = getRequiredTypeInfo(((DecoratingProxy) factory).getDecoratedClass(), ConverterFactory.class);
		}
		if (typeInfo == null) {
			throw new IllegalArgumentException("Unable to determine source type <S> and target type <T> for your " +
					"ConverterFactory [" + factory.getClass().getName() + "]; does the class parameterize those types?");
		}
		//ConverterFactoryAdapter是将ConverterFactory转换为通用的GenericAdapter
		addConverter(new ConverterFactoryAdapter(factory,
				new ConvertiblePair(typeInfo[0].toClass(), typeInfo[1].toClass())));
	}

//移除某个转换器
	@Override
	public void removeConvertible(Class<?> sourceType, Class<?> targetType) {
	//可以看出是converters管理某个转换器的删除
		this.converters.remove(sourceType, targetType);
		//清空缓存
		invalidateCache();
	}

	// ConversionService implementation

	@Override
	public boolean canConvert(@Nullable Class<?> sourceType, Class<?> targetType) {
		Assert.notNull(targetType, "Target type to convert to cannot be null");
		//将Class包装为TypeDescriptor,然后交给重载方法进行处理
		return canConvert((sourceType != null ? TypeDescriptor.valueOf(sourceType) : null),
				TypeDescriptor.valueOf(targetType));
	}

	@Override
	public boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
		Assert.notNull(targetType, "Target type to convert to cannot be null");
		if (sourceType == null) {
			return true;
		}
		//能否进行转换就是去找到有无可用的转换器
		//这里如果一开始缓存中没有,那么找到后会加入缓存中,这样一会进行转换的时候,就会直接从缓存中取
		//如果找不到也会放入缓存集合--相当于做个标记
		GenericConverter converter = getConverter(sourceType, targetType);
		return (converter != null);
	}

	/**
      是否不需要进行任何类型转换
	 */
	public boolean canBypassConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
		Assert.notNull(targetType, "Target type to convert to cannot be null");
		if (sourceType == null) {
			return true;
		}
		//如果不需要进行任何类型转换,那么getConverter会返回NO_OP_CONVERTER---表示当前类型对不需要进行转换
		GenericConverter converter = getConverter(sourceType, targetType);
		return (converter == NO_OP_CONVERTER);
	}

	@Override
	@SuppressWarnings("unchecked")
	@Nullable
	//将source对象转换为targetType类型
	public <T> T convert(@Nullable Object source, Class<T> targetType) {
		Assert.notNull(targetType, "Target type to convert to cannot be null");
		//最终调用的是重载方法来进行处理
		return (T) convert(source, TypeDescriptor.forObject(source), TypeDescriptor.valueOf(targetType));
	}

	@Override
	@Nullable
	public Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
		Assert.notNull(targetType, "Target type to convert to cannot be null");
		//如果原对象类型为null,那么对应的source对象肯定也为null
		if (sourceType == null) {
			Assert.isTrue(source == null, "Source must be [null] if source type == [null]");
			//convertNullSource:如果targetType是Optional类型,最终返回的是Optional.empty()
			//否则返回null
			//handleResult:返回第三个参数作为返回结果,如果第三个参数为null,会抛出异常
			return handleResult(null, targetType, convertNullSource(null, targetType));
		}
		//sourceType必须是Source的类型--isInstance---》InstanceOf
		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) {
		    //ConversionUtils.invokeConverter最终就是调用converter的converter方法
			Object result = ConversionUtils.invokeConverter(converter, source, sourceType, targetType);
			//主要对第三个参数是否为空进行校验
			return handleResult(sourceType, targetType, result);
		}
		//source为null,直接返回null,或者target是source的父类,返回直接返回source即可,不需要进行任何类型转换操作
		return handleConverterNotFound(source, sourceType, targetType);
	}

	@Nullable
	public Object convert(@Nullable Object source, TypeDescriptor targetType) {
		return convert(source, TypeDescriptor.forObject(source), targetType);
	}

	@Override
	public String toString() {
		return this.converters.toString();
	}

	// Protected template methods
    
	@Nullable
	protected Object convertNullSource(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
		//null--->Optional,那么最终转换后得到的是Optional.empty()
		if (targetType.getObjectType() == Optional.class) {
			return Optional.empty();
		}
		return null;
	}

	@Nullable
	protected GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
		//构建缓存key
		ConverterCacheKey key = new ConverterCacheKey(sourceType, targetType);
		//先尝试从缓存中去获取
		GenericConverter converter = this.converterCache.get(key);
		if (converter != null) {
			//缓存中存在
			//这里提前说一下:如果某个类型对不存在与之关联的转换器,那么在第一次查找无果后
			//会在缓存中进行标记,即当前key--->NO_MATCH
			//因此如果这里存在转换器,但是为NO_MATCH ,表示不存在对应的转换器可以转换该类型对,返回null即可
			return (converter != NO_MATCH ? converter : null);
		}
        //converters负责通过类型对去查找到指定的转换器
		converter = this.converters.find(sourceType, targetType);
		//如果找不到
		if (converter == null) {
		//如果source和target之间是父子关系,那么返回NO_OP_CONVERTER,表示不需要进行类型转换
		//否则返回null
			converter = getDefaultConverter(sourceType, targetType);
		}
        //如果到这里找到了对应的转换器,那么会放入缓存中
		if (converter != null) {
			this.converterCache.put(key, converter);
			return converter;
		}
        //走到这里,说明找不到,那么当前类型对会和一个NO_MATCH的转换器进行关联
		this.converterCache.put(key, NO_MATCH);
		return null;
	}
	
			//如果source和target之间是父子关系,那么返回NO_OP_CONVERTER,表示不需要进行类型转换
		//否则返回null
	@Nullable
	protected GenericConverter getDefaultConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
		return (sourceType.isAssignableTo(targetType) ? NO_OP_CONVERTER : null);
	}

	// ---------------------Internal helpers:内部帮助的方法 ---------------------

	@Nullable
	private ResolvableType[] getRequiredTypeInfo(Class<?> converterClass, Class<?> genericIfc) {
	   //对传入的class类进行包装,然后返回包装后的ResolvableType 
		ResolvableType resolvableType = ResolvableType.forClass(converterClass).as(genericIfc);
		//获取此类的泛型参数数组,这些获取到的泛型参数也会被ResolvableType进行包装
		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();
	}

	//source为null,直接返回null,或者target是source的父类,返回直接返回source即可,不需要进行任何类型转换操作
	@Nullable
	private Object handleConverterNotFound(
			@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {

		if (source == null) {
			assertNotPrimitiveTargetType(sourceType, targetType);
			return null;
		}
		if ((sourceType == null || sourceType.isAssignableTo(targetType)) &&
				targetType.getObjectType().isInstance(source)) {
			return source;
		}
		throw new ConverterNotFoundException(sourceType, targetType);
	}

	@Nullable
	private Object handleResult(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType, @Nullable Object result) {
		if (result == null) {
			assertNotPrimitiveTargetType(sourceType, targetType);
		}
		return result;
	}

	private void assertNotPrimitiveTargetType(@Nullable 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"));
		}
	}

	/**
	 * 将Converter适配为GenericConverter
	 */
	@SuppressWarnings("unchecked")
	private final class ConverterAdapter implements ConditionalGenericConverter {
        //需要进行适配的converter
		private final Converter<Object, Object> converter;
        //类型对
		private final ConvertiblePair typeInfo;
       //保存目标对象类型相关信息
		private final ResolvableType targetType;
         
         //真正进行适配的地方在ConverterAdapter构造函数这里完成
		public ConverterAdapter(Converter<?, ?> converter, ResolvableType sourceType, ResolvableType targetType) {
			this.converter = (Converter<Object, Object>) converter;
			this.typeInfo = new ConvertiblePair(sourceType.toClass(), targetType.toClass());
			this.targetType = targetType;
		}

		@Override
		public Set<ConvertiblePair> getConvertibleTypes() {
			return Collections.singleton(this.typeInfo);
		}

		@Override
		public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
			// Check raw type first...
			if (this.typeInfo.getTargetType() != targetType.getObjectType()) {
				return false;
			}
			// Full check for complex generic type match required?
			ResolvableType rt = targetType.getResolvableType();
			if (!(rt.getType() instanceof Class) && !rt.isAssignableFrom(this.targetType) &&
					!this.targetType.hasUnresolvableGenerics()) {
				return false;
			}
			return !(this.converter instanceof ConditionalConverter) ||
					((ConditionalConverter) this.converter).matches(sourceType, targetType);
		}

		@Override
		@Nullable
		public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
			if (source == null) {
				return convertNullSource(sourceType, targetType);
			}
			//调用构造函数传入需要进行适配的转化器的convert方法
			return this.converter.convert(source);
		}

		@Override
		public String toString() {
			return (this.typeInfo + " : " + this.converter);
		}
	}

	/**
     将ConverterFactory转化为GenericConverter
	 */
	@SuppressWarnings("unchecked")
	private final class ConverterFactoryAdapter implements ConditionalGenericConverter {
      
		private final ConverterFactory<Object, Object> converterFactory;

		private final ConvertiblePair typeInfo;

		public ConverterFactoryAdapter(ConverterFactory<?, ?> converterFactory, ConvertiblePair typeInfo) {
			this.converterFactory = (ConverterFactory<Object, Object>) converterFactory;
			this.typeInfo = typeInfo;
		}

		@Override
		public Set<ConvertiblePair> getConvertibleTypes() {
			return Collections.singleton(this.typeInfo);
		}

		@Override
		public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
			boolean matches = true;
			if (this.converterFactory instanceof ConditionalConverter) {
				matches = ((ConditionalConverter) this.converterFactory).matches(sourceType, targetType);
			}
			if (matches) {
				Converter<?, ?> converter = this.converterFactory.getConverter(targetType.getType());
				if (converter instanceof ConditionalConverter) {
					matches = ((ConditionalConverter) converter).matches(sourceType, targetType);
				}
			}
			return matches;
		}

		@Override
		@Nullable
		public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
			if (source == null) {
				return convertNullSource(sourceType, targetType);
			}
			return this.converterFactory.getConverter(targetType.getObjectType()).convert(source);
		}

		@Override
		public String toString() {
			return (this.typeInfo + " : " + this.converterFactory);
		}
	}

	/**
	 缓存key
	 */
	private static final class ConverterCacheKey implements Comparable<ConverterCacheKey> {

		private final TypeDescriptor sourceType;

		private final TypeDescriptor targetType;

		public ConverterCacheKey(TypeDescriptor sourceType, TypeDescriptor targetType) {
			this.sourceType = sourceType;
			this.targetType = targetType;
		}

		@Override
		public boolean equals(@Nullable Object other) {
			if (this == other) {
				return true;
			}
			if (!(other instanceof ConverterCacheKey)) {
				return false;
			}
			ConverterCacheKey otherKey = (ConverterCacheKey) other;
			return (this.sourceType.equals(otherKey.sourceType)) &&
					this.targetType.equals(otherKey.targetType);
		}

		@Override
		public int hashCode() {
			return (this.sourceType.hashCode() * 29 + this.targetType.hashCode());
		}

		@Override
		public String toString() {
			return ("ConverterCacheKey [sourceType = " + this.sourceType +
					", targetType = " + this.targetType + "]");
		}

		@Override
		public int compareTo(ConverterCacheKey other) {
			int result = this.sourceType.getResolvableType().toString().compareTo(
					other.sourceType.getResolvableType().toString());
			if (result == 0) {
				result = this.targetType.getResolvableType().toString().compareTo(
						other.targetType.getResolvableType().toString());
			}
			return result;
		}
	}

	/**
	它管理所有转换器,包括添加、删除、查找。
	 */
	private static class Converters {
       //存取通用的转换器,并不限定转换类型,一般用于兜底
		private final Set<GenericConverter> globalConverters = new CopyOnWriteArraySet<>();
       //指定了类型对,对应的转换器们的映射关系
       //ConvertiblePair:表示一对,包含sourceType和targetType
       //ConvertersForPair:这一对对应的转换器们(因为能处理一对的可能存在多个转换器),内部使用一个双端队列Deque来存储,保证顺序   
		private final Map<ConvertiblePair, ConvertersForPair> converters = new ConcurrentHashMap<>(256);
        
        //添加动作
		public void add(GenericConverter converter) {
		//先获取当前转换器可以转换的类型对
			Set<ConvertiblePair> convertibleTypes = converter.getConvertibleTypes();
			if (convertibleTypes == null) {
				Assert.state(converter instanceof ConditionalConverter,
						"Only conditional converters may return null convertible types");
				//如果为空,说明在进行适配前,被适配的转换器并不是	GenericConverter 类型
				//那么放入全局集合中	
				this.globalConverters.add(converter);
			}
			else {
			//类型对和转换器时多对多的关系,通过convertibleTypes方法,我们可以得到一个转换器可以转换的所有类型
			//但是我们还需要知道一个类型可以被多少个转换器处理,下面的循环干的就是这个事情
				for (ConvertiblePair convertiblePair : convertibleTypes) {
				//调用的是返回的ConvertersForPair的add方法
					getMatchableConverters(convertiblePair).add(converter);
				}
			}
		}

		private ConvertersForPair getMatchableConverters(ConvertiblePair convertiblePair) {
		//如果该类型对在converters集合中还不存在,那么会创建一个与当前key关联的ConvertersForPair放入map集合中
			return this.converters.computeIfAbsent(convertiblePair, k -> new ConvertersForPair());
		}

		public void remove(Class<?> sourceType, Class<?> targetType) {
			this.converters.remove(new ConvertiblePair(sourceType, targetType));
		}

      //查找某一个转换器
		@Nullable
		public GenericConverter find(TypeDescriptor sourceType, TypeDescriptor targetType) {
			// Search the full type hierarchy
			//getClassHierarchy的作用是啥子呢? 举个栗子:
			//getClassHierarchy(User.class)
			//class User{}
			//返回的集合里面包含User.class和Object.class
			//该方法返回的是某个类型的继承树,往上走的
			List<Class<?>> sourceCandidates = getClassHierarchy(sourceType.getType());
			List<Class<?>> targetCandidates = getClassHierarchy(targetType.getType());
			//如果这里想把class User{}转换为class Peo{}
			//那么这里会循环四次:
			//User--->Peo User-->Object Object--->Peo Object--->Object
			for (Class<?> sourceCandidate : sourceCandidates) {
				for (Class<?> targetCandidate : targetCandidates) {
				    //构造类型对
					ConvertiblePair convertiblePair = new ConvertiblePair(sourceCandidate, targetCandidate);
					//尝试从已经注册的集合中获取到需要的转换器
					GenericConverter converter = getRegisteredConverter(sourceType, targetType, convertiblePair);
					if (converter != null) {
						return converter;
					}
				}
			}
			return null;
		}

		@Nullable
		private GenericConverter getRegisteredConverter(TypeDescriptor sourceType,
				TypeDescriptor targetType, ConvertiblePair convertiblePair) {

			// Check specifically registered converters
			//从转换器集合中寻找某个转换器---这里返回的ConvertersForPair代表能够转换当前类型对的转换器集合
			//下面会分析
			ConvertersForPair convertersForPair = this.converters.get(convertiblePair);
			if (convertersForPair != null) {
				//转换器存在
				   //返回第一个匹配的转换器---因为存在某些转换器虽然可以转换该类型对,但是它实现了ConditionalConverter接口
				   //还需要调用match进行判断
				GenericConverter converter = convertersForPair.getConverter(sourceType, targetType);
				if (converter != null) {
					return converter;
				}
			}
			//从这里可以看出globalConverter 实现了兜底策略
			// Check ConditionalConverters for a dynamic match
			for (GenericConverter globalConverter : this.globalConverters) {
				if (((ConditionalConverter) globalConverter).matches(sourceType, targetType)) {
					return globalConverter;
				}
			}
			return null;
		}

//下面的就不分析,感兴趣的自己研究吧
		private List<Class<?>> getClassHierarchy(Class<?> type) {
			List<Class<?>> hierarchy = new ArrayList<>(20);
			Set<Class<?>> visited = new HashSet<>(20);
			addToClassHierarchy(0, ClassUtils.resolvePrimitiveIfNecessary(type), false, hierarchy, visited);
			boolean array = type.isArray();

			int i = 0;
			while (i < hierarchy.size()) {
				Class<?> candidate = hierarchy.get(i);
				candidate = (array ? candidate.getComponentType() : ClassUtils.resolvePrimitiveIfNecessary(candidate));
				Class<?> superclass = candidate.getSuperclass();
				if (superclass != null && superclass != Object.class && superclass != Enum.class) {
					addToClassHierarchy(i + 1, candidate.getSuperclass(), array, hierarchy, visited);
				}
				addInterfacesToClassHierarchy(candidate, array, hierarchy, visited);
				i++;
			}

			if (Enum.class.isAssignableFrom(type)) {
				addToClassHierarchy(hierarchy.size(), Enum.class, array, hierarchy, visited);
				addToClassHierarchy(hierarchy.size(), Enum.class, false, hierarchy, visited);
				addInterfacesToClassHierarchy(Enum.class, array, hierarchy, visited);
			}

			addToClassHierarchy(hierarchy.size(), Object.class, array, hierarchy, visited);
			addToClassHierarchy(hierarchy.size(), Object.class, false, hierarchy, visited);
			return hierarchy;
		}

		private void addInterfacesToClassHierarchy(Class<?> type, boolean asArray,
				List<Class<?>> hierarchy, Set<Class<?>> visited) {

			for (Class<?> implementedInterface : type.getInterfaces()) {
				addToClassHierarchy(hierarchy.size(), implementedInterface, asArray, hierarchy, visited);
			}
		}

		private void addToClassHierarchy(int index, Class<?> type, boolean asArray,
				List<Class<?>> hierarchy, Set<Class<?>> visited) {

			if (asArray) {
				type = Array.newInstance(type, 0).getClass();
			}
			if (visited.add(type)) {
				hierarchy.add(index, type);
			}
		}

		@Override
		public String toString() {
			StringBuilder builder = new StringBuilder();
			builder.append("ConversionService converters =\n");
			for (String converterString : getConverterStrings()) {
				builder.append('\t').append(converterString).append('\n');
			}
			return builder.toString();
		}

		private List<String> getConverterStrings() {
			List<String> converterStrings = new ArrayList<>();
			for (ConvertersForPair convertersForPair : this.converters.values()) {
				converterStrings.add(convertersForPair.toString());
			}
			Collections.sort(converterStrings);
			return converterStrings;
		}
	}

	/**
	 * 一个类型对可以被多少个转换器进行处理
	 */
	private static class ConvertersForPair {
        //存放可以转换当前类型对的集合
		private final Deque<GenericConverter> converters = new ConcurrentLinkedDeque<>();

		public void add(GenericConverter converter) {
			this.converters.addFirst(converter);
		}
       
       //返回第一个匹配的转换器
		@Nullable
		public GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
			for (GenericConverter converter : this.converters) {
			//如果是ConditionalGenericConverter类型的转换器,还需要通过match方法判断当前转换器是否符合转换条件
				if (!(converter instanceof ConditionalGenericConverter) ||
						((ConditionalGenericConverter) converter).matches(sourceType, targetType)) {
					return converter;
				}
			}
			return null;
		}

		@Override
		public String toString() {
			return StringUtils.collectionToCommaDelimitedString(this.converters);
		}
	}

	/**
	 * 当前类型对不需要进行任何类型转换的时候,会返回这个转换器
	 */
	private static class NoOpConverter implements GenericConverter {

		private final String name;

		public NoOpConverter(String name) {
			this.name = name;
		}

		@Override
		@Nullable
		public Set<ConvertiblePair> getConvertibleTypes() {
			return null;
		}

		@Override
		@Nullable
		public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
			return source;
		}

		@Override
		public String toString() {
			return this.name;
		}
	}

}

如果大家坚持看完了这700多行源码,会发现通用转换器服务类不过如此,其实源码没大家想的那么难

GenericConversionService实现了转换器管理、转换服务的所有功能,是可以直接面向开发者使用的。但是开发者使用时可能并不知道需要注册哪些转换器来保证程序正常运转,Spring并不能要求开发者知晓其内建实现。基于此,Spring在3.1又提供了一个默认实现DefaultConversionService,它对使用者更友好。

DefaultConversionService

Spirng容器默认使用的转换服务实现,继承自GenericConversionService,在其基础行只做了一件事:构造时添加内建的默认转换器们。从而天然具备有了基本的类型转换能力,适用于不同的环境。如:xml解析、@Value解析、http协议参数自动转换等等。

public class DefaultConversionService extends GenericConversionService {
     //相信大部分看到他的第一眼,一定认为spring是想实例单例模式,但是事实并非如此,只猜到了一半
	@Nullable
	private static volatile DefaultConversionService sharedInstance;

	/**
      构造函数都没有设置成私有,显然印证了上面的分析
	 */
	public DefaultConversionService() {
	//添加很多默认的转换器
		addDefaultConverters(this);
	}

	/**
返回一个共享的默认 ConversionService 实例,在需要时懒惰地构建它。
注意:我们强烈建议为自定义目的构建单独的 ConversionService 实例。
此访问器仅用作需要简单类型强制但无法以任何其他方式访问寿命更长的 ConversionService 实例的代码路径的后备。
	 */
	public static ConversionService getSharedInstance() {
		DefaultConversionService cs = sharedInstance;
		//简单的双重锁实现单例模式
		if (cs == null) {
			synchronized (DefaultConversionService.class) {
				cs = sharedInstance;
				if (cs == null) {
					cs = new DefaultConversionService();
					sharedInstance = cs;
				}
			}
		}
		return cs;
	}

	/**
添加适用于大多数环境的转换器。
	 */
	public static void addDefaultConverters(ConverterRegistry converterRegistry) {
	//scalar是标量的意思,这里添加的都是一些和数字相关的转换器
		addScalarConverters(converterRegistry);
		//添加与集合相关的转换器
		addCollectionConverters(converterRegistry);

       //JSR310转换器
		converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry));
		converterRegistry.addConverter(new StringToTimeZoneConverter());
		converterRegistry.addConverter(new ZoneIdToTimeZoneConverter());
		converterRegistry.addConverter(new ZonedDateTimeToCalendarConverter());

        //之前系列讲过的,兜底转换器
		converterRegistry.addConverter(new ObjectToObjectConverter());
		converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry));
		converterRegistry.addConverter(new FallbackObjectToStringConverter());
		converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService) converterRegistry));
	}
	
	public static void addCollectionConverters(ConverterRegistry converterRegistry) {
		ConversionService conversionService = (ConversionService) converterRegistry;

		converterRegistry.addConverter(new ArrayToCollectionConverter(conversionService));
		converterRegistry.addConverter(new CollectionToArrayConverter(conversionService));

		converterRegistry.addConverter(new ArrayToArrayConverter(conversionService));
		converterRegistry.addConverter(new CollectionToCollectionConverter(conversionService));
		converterRegistry.addConverter(new MapToMapConverter(conversionService));

		converterRegistry.addConverter(new ArrayToStringConverter(conversionService));
		converterRegistry.addConverter(new StringToArrayConverter(conversionService));

		converterRegistry.addConverter(new ArrayToObjectConverter(conversionService));
		converterRegistry.addConverter(new ObjectToArrayConverter(conversionService));

		converterRegistry.addConverter(new CollectionToStringConverter(conversionService));
		converterRegistry.addConverter(new StringToCollectionConverter(conversionService));

		converterRegistry.addConverter(new CollectionToObjectConverter(conversionService));
		converterRegistry.addConverter(new ObjectToCollectionConverter(conversionService));

		converterRegistry.addConverter(new StreamConverter(conversionService));
	}

	private static void addScalarConverters(ConverterRegistry converterRegistry) {
		converterRegistry.addConverterFactory(new NumberToNumberConverterFactory());

		converterRegistry.addConverterFactory(new StringToNumberConverterFactory());
		converterRegistry.addConverter(Number.class, String.class, new ObjectToStringConverter());

		converterRegistry.addConverter(new StringToCharacterConverter());
		converterRegistry.addConverter(Character.class, String.class, new ObjectToStringConverter());

		converterRegistry.addConverter(new NumberToCharacterConverter());
		converterRegistry.addConverterFactory(new CharacterToNumberFactory());

		converterRegistry.addConverter(new StringToBooleanConverter());
		converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter());

		converterRegistry.addConverterFactory(new StringToEnumConverterFactory());
		converterRegistry.addConverter(new EnumToStringConverter((ConversionService) converterRegistry));

		converterRegistry.addConverterFactory(new IntegerToEnumConverterFactory());
		converterRegistry.addConverter(new EnumToIntegerConverter((ConversionService) converterRegistry));

		converterRegistry.addConverter(new StringToLocaleConverter());
		converterRegistry.addConverter(Locale.class, String.class, new ObjectToStringConverter());

		converterRegistry.addConverter(new StringToCharsetConverter());
		converterRegistry.addConverter(Charset.class, String.class, new ObjectToStringConverter());

		converterRegistry.addConverter(new StringToCurrencyConverter());
		converterRegistry.addConverter(Currency.class, String.class, new ObjectToStringConverter());

		converterRegistry.addConverter(new StringToPropertiesConverter());
		converterRegistry.addConverter(new PropertiesToStringConverter());

		converterRegistry.addConverter(new StringToUUIDConverter());
		converterRegistry.addConverter(UUID.class, String.class, new ObjectToStringConverter());
	}

}

特别强调:转换器的注册顺序非常重要,这决定了通用转换器的匹配结果(谁在前,优先匹配谁,first win)。

JSR310转换器只看到TimeZone、ZoneId等转换,怎么没看见更为常用的LocalDate、LocalDateTime等这些类型转换呢?难道Spring默认是不支持的?

  • 答:当然不是。 这么常见的场景Spring怎能会不支持呢?不过与其说这是类型转换,倒不如说是格式化更合适。所以放在该系列后几篇关于格式化章节中再做讲述

最后,需要特别强调的是:addDefaultConverters是一个静态方法,并且还是public的访问权限,且不仅仅只有本类调用。

实际上,DefaultConversionService仅仅只做了这一件事,所以任何地方只要调用了该静态方法都能达到前者相同的效果,使用上可谓给与了较大的灵活性。

比如Spring Boot环境下不是使用DefaultConversionService而是ApplicationConversionService,后者是对FormattingConversionService扩展,这个话题放在后面详解。

Spring Boot在web环境默认向容器注册了一个WebConversionService,因此你有需要可直接@Autowired使用

ConversionServiceFactoryBean

顾名思义,它是用于产生ConversionService类型转换服务的工厂Bean,为了方便和Spring容器整合而使用。

因为该类源码中出现了ConversionServiceFactory,并且这个类源码很短,我就直接贴出来讲一下:

public final class ConversionServiceFactory {

	private ConversionServiceFactory() {
	}

	/**
	 * 将传入的自定义转换器都注册到注册中心里面去
	 */
	public static void registerConverters(@Nullable Set<?> converters, ConverterRegistry registry) {
		if (converters != null) {
		//下面操作就不多说了,这里registry调用的方法都是GenericConversionService类中的
			for (Object converter : converters) {
				if (converter instanceof GenericConverter) {
					registry.addConverter((GenericConverter) converter);
				}
				else if (converter instanceof Converter<?, ?>) {
					registry.addConverter((Converter<?, ?>) converter);
				}
				else if (converter instanceof ConverterFactory<?, ?>) {
					registry.addConverterFactory((ConverterFactory<?, ?>) converter);
				}
				else {
					throw new IllegalArgumentException("Each converter object must implement one of the " +
							"Converter, ConverterFactory, or GenericConverter interfaces");
				}
			}
		}
	}

}
//负责生产ConversionService的bean工厂
public class ConversionServiceFactoryBean implements FactoryBean<ConversionService>, InitializingBean {
    //自定义转换器集合
	@Nullable
	private Set<?> converters;
    //通用的转换器类---上面分析过
	@Nullable
	private GenericConversionService conversionService;

	/**
     调用此方法,可以向注册中心注册自定义的转换器
	 */
	public void setConverters(Set<?> converters) {
		this.converters = converters;
	}
    
    //因为该类实现了InitializingBean接口,因此需要重写该方法,在bean属性被设置后,会回调该接口 
	@Override
	public void afterPropertiesSet() {
	//创建默认的转换器服务
		this.conversionService = createConversionService();
		//注册自定义转换器,ConversionServiceFactory这个类上面分析过
		ConversionServiceFactory.registerConverters(this.converters, this.conversionService);
	}

	protected GenericConversionService createConversionService() {
		return new DefaultConversionService();
	}

	// implementing FactoryBean---实现FactoryBean的接口

	@Override
	@Nullable
	public ConversionService getObject() {
		return this.conversionService;
	}

	@Override
	public Class<? extends ConversionService> getObjectType() {
		return GenericConversionService.class;
	}

	@Override
	public boolean isSingleton() {
		return true;
	}

}

这里只有两个信息量需要关注:

  • 使用的是DefaultConversionService,因此那一大串的内建转换器们都会被添加进来的
  • 自定义转换器可以通过setConverters()方法添加进来
  • 值得注意的是方法入参是Set< ? >并没有明确泛型类型,因此那三种转换器(1:1/1:N/N:N)你是都可以添加.

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com