欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring源码解析之-TypeConverter、TypeConverterDelegate分析

程序员文章站 2022-05-04 11:43:24
目录一、介绍二、源码分析2.1 convertIfNecessary 方法解析2.2 findDefaultEditor 方法解析2.3 doConvertValue 方法解析2.3 convertToTypedArray方法解析2.3 convertToTypedCollection方法解析三、小结一、介绍TypeConverter 类主要是 负责类型转换,其实现类是 TypeConverterSupport,但是所有的具体实现都是在TypeConverterDelegate 里面完成的.二、源码分...

一、介绍

TypeConverter 类主要是 负责类型转换,其实现类是 TypeConverterSupport,但是所有的具体实现都是在TypeConverterDelegate 里面完成的.

二、源码分析

TypeConverterDelegate 里面总共包含的方法如下:
Spring源码解析之-TypeConverter、TypeConverterDelegate分析
这里主要分析一些主要的方法

2.1 convertIfNecessary 方法解析

public <T> T convertIfNecessary(@Nullable String propertyName, @Nullable Object oldValue, @Nullable Object newValue,
			@Nullable Class<T> requiredType, @Nullable TypeDescriptor typeDescriptor) throws IllegalArgumentException {

		// 根据requiredType 和 propertyName 获取对应的定制编辑器
		PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);

		ConversionFailedException conversionAttemptEx = null;

		// 获取对应的conversionService
		ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
		if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) {
		    // 为newValue 创建一个类型描述器
			TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
			// 判断是否能sourceTypeDesc 转换为需要的typeDescriptor,如果可以
			//直接调用conversionService.convert 进行返回
			if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
				try {
					return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
				}
				catch (ConversionFailedException ex) {
					// fallback to default conversion logic below
					conversionAttemptEx = ex;
				}
			}
		}
		Object convertedValue = newValue;
		// 自定义editor 不为空 或者 对应的值 不是 需要的类型
		if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
		// 如果需要的类型是集合类型,并且值是String 类型(String⇒ 集合)
			if (typeDescriptor != null && requiredType != null && Collection.class.isAssignableFrom(requiredType) &&
					convertedValue instanceof String) {
			    // 获取集合里面元素的类型描述器
				TypeDescriptor elementTypeDesc = typeDescriptor.getElementTypeDescriptor();
				if (elementTypeDesc != null) {
				    // 获取对应的类型
					Class<?> elementType = elementTypeDesc.getType();
					if (Class.class == elementType || Enum.class.isAssignableFrom(elementType)) {
					    //将String字符串逗号分隔开,转换成字符串数组
						convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
					}
				}
			}
			//如果自定义编辑器 为null,就根据requiredType 设置相对应的编辑器
			if (editor == null) {
				editor = findDefaultEditor(requiredType);
			}
			//对convertedValue 进行相关的转换
			convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor);
		}

		boolean standardConversion = false;

		if (requiredType != null) {
            // 这里都是一些标准的类型转换 ,根据各种类型调用相应的方法
			if (convertedValue != null) {
			// 如果是Object类型,直接强制转换并返回
				if (Object.class == requiredType) {
					return (T) convertedValue;
				}
				else if (requiredType.isArray()) {
					//如果需要的类型是枚举类型
					if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {
					// 先将 转换为 逗号分隔的String 数组
						convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
					}
					// 转换为数组
					return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType());
				}
				else if (convertedValue instanceof Collection) {
					//如果convertedValue 是集合类型 ,进行相关的转换
					convertedValue = convertToTypedCollection(
							(Collection<?>) convertedValue, propertyName, requiredType, typeDescriptor);
					standardConversion = true;
				}
				else if (convertedValue instanceof Map) {
					// 如果确定,将键和值转换为相应的目标类型
					convertedValue = convertToTypedMap(
							(Map<?, ?>) convertedValue, propertyName, requiredType, typeDescriptor);
					standardConversion = true;
				}
				// 如果convertedValue 是数组类型,并且 长度为1 ,那就把get(0) 赋值给本身
				if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) {
					convertedValue = Array.get(convertedValue, 0);
					standardConversion = true;
				}
				// 如果需要的类型是 String ,并且convertedValue 的类型是基本类型或者装箱类型,那就直接toString 后强行转换
				if (String.class == requiredType && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) {
					// We can stringify any primitive value...
					return (T) convertedValue.toString();
				}
				else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
					if (conversionAttemptEx == null && !requiredType.isInterface() && !requiredType.isEnum()) {
						try {
							Constructor<T> strCtor = requiredType.getConstructor(String.class);
							return BeanUtils.instantiateClass(strCtor, convertedValue);
						}
						catch (NoSuchMethodException ex) {
							// proceed with field lookup
							if (logger.isTraceEnabled()) {
								logger.trace("No String constructor found on type [" + requiredType.getName() + "]", ex);
							}
						}
						catch (Exception ex) {
							if (logger.isDebugEnabled()) {
								logger.debug("Construction via String failed for type [" + requiredType.getName() + "]", ex);
							}
						}
					}
					String trimmedValue = ((String) convertedValue).trim();
					if (requiredType.isEnum() && trimmedValue.isEmpty()) {
						// It's an empty enum identifier: reset the enum value to null.
						return null;
					}
					convertedValue = attemptToConvertStringToEnum(requiredType, trimmedValue, convertedValue);
					standardConversion = true;
				}
				else if (convertedValue instanceof Number && Number.class.isAssignableFrom(requiredType)) {
					convertedValue = NumberUtils.convertNumberToTargetClass(
							(Number) convertedValue, (Class<Number>) requiredType);
					standardConversion = true;
				}
			}
			else {
				// convertedValue == null
				if (requiredType == Optional.class) {
					convertedValue = Optional.empty();
				}
			}

			if (!ClassUtils.isAssignableValue(requiredType, convertedValue)) {
				if (conversionAttemptEx != null) {
					// Original exception from former ConversionService call above...
					throw conversionAttemptEx;
				}
				else if (conversionService != null && typeDescriptor != null) {
					// ConversionService not tried before, probably custom editor found
					// but editor couldn't produce the required type...
					TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
					if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
						return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
					}
				}

				// Definitely doesn't match: throw IllegalArgumentException/IllegalStateException
				StringBuilder msg = new StringBuilder();
				msg.append("Cannot convert value of type '").append(ClassUtils.getDescriptiveType(newValue));
				msg.append("' to required type '").append(ClassUtils.getQualifiedName(requiredType)).append("'");
				if (propertyName != null) {
					msg.append(" for property '").append(propertyName).append("'");
				}
				if (editor != null) {
					msg.append(": PropertyEditor [").append(editor.getClass().getName()).append(
							"] returned inappropriate value of type '").append(
							ClassUtils.getDescriptiveType(convertedValue)).append("'");
					throw new IllegalArgumentException(msg.toString());
				}
				else {
					msg.append(": no matching editors or conversion strategy found");
					throw new IllegalStateException(msg.toString());
				}
			}
		}

		if (conversionAttemptEx != null) {
			if (editor == null && !standardConversion && requiredType != null && Object.class != requiredType) {
				throw conversionAttemptEx;
			}
			logger.debug("Original ConversionService attempt failed - ignored since " +
					"PropertyEditor based conversion eventually succeeded", conversionAttemptEx);
		}

		return (T) convertedValue;
	}

2.2 findDefaultEditor 方法解析

	private PropertyEditor findDefaultEditor(@Nullable Class<?> requiredType) {
		PropertyEditor editor = null;
		if (requiredType != null) {
			// No custom editor -> check BeanWrapperImpl's default editors.
			editor = this.propertyEditorRegistry.getDefaultEditor(requiredType);
			if (editor == null && String.class != requiredType) {
				// No BeanWrapper default editor -> check standard JavaBean editor.
				editor = BeanUtils.findEditorByConvention(requiredType);
			}
		}
		return editor;
	}

2.3 doConvertValue 方法解析

private Object doConvertValue(@Nullable Object oldValue, @Nullable Object newValue,
			@Nullable Class<?> requiredType, @Nullable PropertyEditor editor) {

		Object convertedValue = newValue;
        // 如果编辑器不为null ,并且 转换值的类型不是 String
		if (editor != null && !(convertedValue instanceof String)) {
			// 调用setValue 方法
			//如果使用标准的PropertyEditors 的话,那就返回的是完全一样的对象,
			// 这里是调用专门的编辑器的setValue方法进行从非String 转到需要的类型上
			try {
				editor.setValue(convertedValue);
				Object newConvertedValue = editor.getValue();
				// 如果不一样,就说明进行了转换,需要将convertedValue 替换为转换后的值
				if (newConvertedValue != convertedValue) {
					convertedValue = newConvertedValue;
					// 这里将editor 置空,editor 已经进行了正确的转换,不需要再将其用于setAsText 的调用
					editor = null;
				}
			}
			catch (Exception ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("PropertyEditor [" + editor.getClass().getName() + "] does not support setValue call", ex);
				}
				// 这里没有抛出异常,而是继续运行下面的代码
			}
		}
		Object returnValue = convertedValue;
         // 如果convertedValue  是String[] 数组类型,而需要的类型不是数组类型
         // 那就先将convertedValue 转换为 逗号分隔的String 值
		if (requiredType != null && !requiredType.isArray() && convertedValue instanceof String[]) {
			if (logger.isTraceEnabled()) {
				logger.trace("Converting String array to comma-delimited String [" + convertedValue + "]");
			}
			// 将 String 数组 转换为 逗号分隔的String 值
			convertedValue = StringUtils.arrayToCommaDelimitedString((String[]) convertedValue);
		}
		if (convertedValue instanceof String) {
			if (editor != null) {
				if (logger.isTraceEnabled()) {
					logger.trace("Converting String to [" + requiredType + "] using property editor [" + editor + "]");
				}
				String newTextValue = (String) convertedValue;
				// 调用 PropertyEditor 的setAsText
				return doConvertTextValue(oldValue, newTextValue, editor);
			}
			// 如果requiredType 是String ,直接赋值并返回
			else if (String.class == requiredType) {
				returnValue = convertedValue;
			}
		}
		return returnValue;
	}

2.3 convertToTypedArray方法解析

private Object convertToTypedArray(Object input, @Nullable String propertyName, Class<?> componentType) {
        // 如果input 是集合类型
		if (input instanceof Collection) {
			// 将集合元素转换为数组元素
			Collection<?> coll = (Collection<?>) input;
			Object result = Array.newInstance(componentType, coll.size());
			int i = 0;
			for (Iterator<?> it = coll.iterator(); it.hasNext(); i++) {
			    // 进行遍历,对逐个元素进行转换
				Object value = convertIfNecessary(
						buildIndexedPropertyName(propertyName, i), null, it.next(), componentType);
				Array.set(result, i, value);
			}
			return result;
		}
		// 如果输入的数组类型
		else if (input.getClass().isArray()) {
			// 对数组里面的元素进行 逐个转换(可能类型一样就不要转换)
			if (componentType.equals(input.getClass().getComponentType()) &&
					!this.propertyEditorRegistry.hasCustomEditorForElement(componentType, propertyName)) {
				return input;
			}
			int arrayLength = Array.getLength(input);
			Object result = Array.newInstance(componentType, arrayLength);
			for (int i = 0; i < arrayLength; i++) {
				Object value = convertIfNecessary(
						buildIndexedPropertyName(propertyName, i), null, Array.get(input, i), componentType);
				Array.set(result, i, value);
			}
			return result;
		}
		else {
			//输入input 既不是集合类型,也不是数组类型,但是要转为数组
			// 就整个转化为一个元素的数组
			Object result = Array.newInstance(componentType, 1);
			Object value = convertIfNecessary(
					buildIndexedPropertyName(propertyName, 0), null, input, componentType);
			Array.set(result, 0, value);
			return result;
		}
	}

2.3 convertToTypedCollection方法解析

private Collection<?> convertToTypedCollection(Collection<?> original, @Nullable String propertyName,
			Class<?> requiredType, @Nullable TypeDescriptor typeDescriptor) {
        // 如果requiredType 不是集合类型,直接返回
		if (!Collection.class.isAssignableFrom(requiredType)) {
			return original;
		}
        // 判断是否是 集合相近的,比如:List,set,ArrayList..
		boolean approximable = CollectionFactory.isApproximableCollectionType(requiredType);
		//不是集合相近的,并且也不能对requiredType复制-注入原始Collection
		if (!approximable && !canCreateCopy(requiredType)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Custom Collection type [" + original.getClass().getName() +
						"] does not allow for creating a copy - injecting original Collection as-is");
			}
			return original;
		}

		boolean originalAllowed = requiredType.isInstance(original);
		TypeDescriptor elementType = (typeDescriptor != null ? typeDescriptor.getElementTypeDescriptor() : null);
		// 集合里面没有指定类型,并且original 就是 requiredType 类型,propertyEditorRegistry里面也没有对应的自定义编辑器,就直接返回
		if (elementType == null && originalAllowed &&
				!this.propertyEditorRegistry.hasCustomEditorForElement(null, propertyName)) {
			return original;
		}

		Iterator<?> it;
		try {
			it = original.iterator();
		}
		catch (Throwable ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Cannot access Collection of type [" + original.getClass().getName() +
						"] - injecting original Collection as-is: " + ex);
			}
			return original;
		}

		Collection<Object> convertedCopy;
		try {
			if (approximable) {
				convertedCopy = CollectionFactory.createApproximateCollection(original, original.size());
			}
			else {
				convertedCopy = (Collection<Object>)
						ReflectionUtils.accessibleConstructor(requiredType).newInstance();
			}
		}
		catch (Throwable ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Cannot create copy of Collection type [" + original.getClass().getName() +
						"] - injecting original Collection as-is: " + ex);
			}
			return original;
		}

		int i = 0;
		// 遍历,进行转换
		for (; it.hasNext(); i++) {
			Object element = it.next();
			String indexedPropertyName = buildIndexedPropertyName(propertyName, i);
			Object convertedElement = convertIfNecessary(indexedPropertyName, null, element,
					(elementType != null ? elementType.getType() : null) , elementType);
			try {
				convertedCopy.add(convertedElement);
			}
			catch (Throwable ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Collection type [" + original.getClass().getName() +
							"] seems to be read-only - injecting original Collection as-is: " + ex);
				}
				return original;
			}
			originalAllowed = originalAllowed && (element == convertedElement);
		}
		return (originalAllowed ? original : convertedCopy);
	}
	// 不是接口、不是抽象类、public 类型、有对应的构造方法
	private boolean canCreateCopy(Class<?> requiredType) {
		return (!requiredType.isInterface() && !Modifier.isAbstract(requiredType.getModifiers()) &&
				Modifier.isPublic(requiredType.getModifiers()) && ClassUtils.hasConstructor(requiredType));
	}

三、小结

这里面的方法都是类型转换相关的.

本文地址:https://blog.csdn.net/mamamalululu00000000/article/details/107304965