Spring源码解析之-ConversionService分析

一、介绍和Demo

ConversionService 是一个 用于类型转换的服务接口,ConversionService 整个涉及的类如下:
在这里插入图片描述
本次主要分析下图部分:
在这里插入图片描述

1.1 demo

    public static void main(String[] args) {
        ConversionService conversionService = new DefaultConversionService();
        // String ==> Integer
        Integer num = conversionService.convert("12345", int.class);
        System.out.println(num);
        // boolean ==> String
        String s = conversionService.convert(false, String.class);
        System.out.println(s);
        //String ==>List
        List<String> arrays = conversionService.convert("1,2,3", List.class);
        System.out.println(arrays);
    }

结果如下,实现了转换

12345
false
[1, 2, 3]

二、源码分析

2.1 ConversionService

ConversionService 一共就四个方法,主要就是 是否能够转换,以及对于的转换方法,有一个 参数 是TypeDescriptor是对于一种类型的封装,里面包含该类型的name、是否是基础类型、集合等判断信息

public interface ConversionService {
	/**
	 * 是否能够进行转换
	 */
	boolean canConvert(@Nullable Class<?> sourceType, Class<?> targetType);
	boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType);
	/**
	 * 进行转换
	 */
	@Nullable
	<T> T convert(@Nullable Object source, Class<T> targetType);
	@Nullable
	Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType);
}

2.2 ConfigurableConversionService

这个接口主要就是 继承了 ConversionService, ConverterRegistry 这两个接口

public interface ConfigurableConversionService extends ConversionService, ConverterRegistry {
}

2.3 ConverterRegistry

这个主要是 注册 或者移除相关的类型转换器,主要方法如下:

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

2.3 GenericConversionService

GenericConversionService 是一个通用的类型转换的基本实现,适用于大部分的情况

2.3.1 内部类

GenericConversionService 类里面有好几个内部类,有一个 Converters 类

  • Converters 类–管理在服务中注册的所有转换器, 后面解析一下相关具体的方法
  • ConverterAdapter —将 convert 转换为 GenericConverter
  • ConverterFactoryAdapter— 将 ConverterFactory 转换为对应的GenericConverter (ConverterFactory 就是一个转换器的工厂,可以将对象从S转换为R的子类型)
  • ConverterCacheKey—与转换器缓存一起使用的key
  • ConvertersForPair— 管理通过ConvertiblePair 注册的转换器

2.3.2 addConverter

添加注入Converter

	public void addConverter(Converter<?, ?> converter) {
	    // 获取对应的soruce、target 类型
		ResolvableType[] typeInfo = getRequiredTypeInfo(converter.getClass(), Converter.class);
		// 如果对应的 类型为空,并且converter 是代理,再一次获取
		if (typeInfo == null && converter instanceof DecoratingProxy) {
			typeInfo = getRequiredTypeInfo(((DecoratingProxy) converter).getDecoratedClass(), Converter.class);
		}
		// 如果 source、target 为null ,就抛出异常
		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?");
		}
		// 添加到内部类 Converters 里面 进行管理
		addConverter(new ConverterAdapter(converter, typeInfo[0], typeInfo[1]));
	}
	@Override
	public void addConverter(GenericConverter converter) {
	    // 加到 GenericConversionService 自定义的类 converters里面
		this.converters.add(converter);
		// 将缓存清空
		invalidateCache();
	}

2.3.3 getConverter

	protected GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
	    // 根据sourceType、targetType 获取对应的KEy 
	    //ConverterCacheKey  重写了equals、hashCode ,这样比较时,就是 比较的 sourceType 和 targetType 是否一致
		ConverterCacheKey key = new ConverterCacheKey(sourceType, targetType);
		// 从缓存获取
		GenericConverter converter = this.converterCache.get(key);
		// 如果不为null, 是 NO_MATCH  就返回 null
		if (converter != null) {
			return (converter != NO_MATCH ? converter : null);
		}
        //从 converters 里面查找 converter
		converter = this.converters.find(sourceType, targetType);
		// 如果为 null ,就返回默认的设置
		if (converter == null) {
			converter = getDefaultConverter(sourceType, targetType);
		}
       // 放入缓存,如果converter  为null,value就设置为
		if (converter != null) {
			this.converterCache.put(key, converter);
			return converter;
		}

		this.converterCache.put(key, NO_MATCH);
		return null;
	}

2.3.4 内部类 Converters

这里的 Converters 是专门负责管理在服务中注册的所有转换器,下面看一下几个具体的方法

2.3.4.1 find

	public GenericConverter find(TypeDescriptor sourceType, TypeDescriptor targetType) {
			// 获取所有的 target、source 的层次结构
			List<Class<?>> sourceCandidates = getClassHierarchy(sourceType.getType());
			List<Class<?>> targetCandidates = getClassHierarchy(targetType.getType());
			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;
		}

2.3 DefaultConversionService

DefaultConversionService 里面主要就是对 一系列的 converter 进行注册, 在构造函数里面直接调用 addDefaultConverters

	/**
	 * Create a new {@code DefaultConversionService} with the set of
	 * {@linkplain DefaultConversionService#addDefaultConverters(ConverterRegistry) default converters}.
	 */
	public DefaultConversionService() {
		addDefaultConverters(this);
	}

三、总结

ConversionService 这块就是 将 source、target 进行转换,并且提供了很多的对应的类型转换方法.

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一直打铁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值