Spring 5 SimpleTypeConverter 源码注释

58 篇文章 1 订阅
56 篇文章 3 订阅

SimpleTypeConverter

/**
 * <p>不在特定目标对象上运行的TypeConverter接口的简单实现。这是使用完整的BeanWrapperImpl实例来实现
 * 任意类型转换需求的替代方法,同时使用相同的转换算法(包括委托给PropertyEditor和ConversionService)。</p>
 * Simple implementation of the {@link TypeConverter} interface that does not operate on
 * a specific target object. This is an alternative to using a full-blown BeanWrapperImpl
 * instance for arbitrary type conversion needs, while using the very same conversion
 * algorithm (including delegation to {@link java.beans.PropertyEditor} and
 * {@link org.springframework.core.convert.ConversionService}) underneath.
 * <p>TypeConverter接口的简单实现,该接口不对特定目标对象进行操作.这是在底层使用完全相同的转换算法(
 * 包括对java.beans.PropertyEditor和org.springframework.core.convert.ConversionService的委派)
 * 使用完全成熟的BeanWrapperImpl实例以满足任意类型转换需求的替代方法</p>
 * <p><b>Note:</b> Due to its reliance on {@link java.beans.PropertyEditor PropertyEditors},
 * SimpleTypeConverter is <em>not</em> thread-safe. Use a separate instance for each thread.
 * <p>注意:由于依赖于PropertyEditors,因此SimpleTypeConverter不是线程安全的.为每个线程使用一个
 * 单独的实例</p>
 * @author Juergen Hoeller
 * @since 2.0
 * @see BeanWrapperImpl
 */
public class SimpleTypeConverter extends TypeConverterSupport {

	public SimpleTypeConverter() {
		this.typeConverterDelegate = new TypeConverterDelegate(this);
		registerDefaultEditors();
	}

}

TypeConverterDelegate

/**
 * Internal helper class for converting property values to target types.
 * <p>用于将属性值转换为目标类型的内部助手类</p>
 *
 * <p>Works on a given {@link PropertyEditorRegistrySupport} instance.
 * Used as a delegate by {@link BeanWrapperImpl} and {@link SimpleTypeConverter}.
 * <p>工作在一个给定 PropertyEditorRegistrySupport实例。由 BeanWrapperImpl 和 SimpleTypeConverter 用作委托</p>
 * @author Juergen Hoeller
 * @author Rob Harrop
 * @author Dave Syer
 * @since 2.0
 * @see BeanWrapperImpl
 * @see SimpleTypeConverter
 */
class TypeConverterDelegate {

	private static final Log logger = LogFactory.getLog(TypeConverterDelegate.class);

	/**
	 * 要使用的属性编辑器注册表
	 */
	private final PropertyEditorRegistrySupport propertyEditorRegistry;

	/**
	 * 要处理的目标对象(作为可传递给编辑器的上下文)
	 */
	@Nullable
	private final Object targetObject;


	/**
	 * Create a new TypeConverterDelegate for the given editor registry.
	 * <p>创建一个新的 TypeConverterDelegate 实例</p>
	 * @param propertyEditorRegistry the editor registry to use -- 要使用的属性编辑器注册表
	 */
	public TypeConverterDelegate(PropertyEditorRegistrySupport propertyEditorRegistry) {
		this(propertyEditorRegistry, null);
	}

	/**
	 * Create a new TypeConverterDelegate for the given editor registry and bean instance.
	 * <p>为给定的编辑器注册表和Bean实例创建一个新的TypeConverterDelegate</p>
	 * @param propertyEditorRegistry the editor registry to use -- 要使用的编辑器注册表
	 * @param targetObject the target object to work on (as context that can be passed to editors)
	 *                     -- 要处理的目标对象(作为可传递给编辑器的上下文)
	 */
	public TypeConverterDelegate(PropertyEditorRegistrySupport propertyEditorRegistry, @Nullable Object targetObject) {
		this.propertyEditorRegistry = propertyEditorRegistry;
		this.targetObject = targetObject;
	}


	/**
	 * Convert the value to the required type for the specified property.
	 * <p>将该值转换为 指定属性 所需的类型</p>
	 * @param propertyName name of the property -- 属性名
	 * @param oldValue the previous value, if available (may be {@code null})
	 *                 -- 前一个值(如果可用)(可以为null)
	 * @param newValue the proposed new value
	 *                 -- 新的值
	 * @param requiredType the type we must convert to
	 * (or {@code null} if not known, for example in case of a collection element)
	 *                     -- 必须转换为的类型(如果不知道,例如集合元素,则为null)
	 * @return the new value, possibly the result of type conversion
	 * 	-- 新值,可能是类型转换的结果
	 * @throws IllegalArgumentException if type conversion failed
	 * 		-- 如果转化失败
	 */
	@Nullable
	public <T> T convertIfNecessary(@Nullable String propertyName, @Nullable Object oldValue,
			Object newValue, @Nullable Class<T> requiredType) throws IllegalArgumentException {
		//将requiredType封装成TypeDescriptor对象,调用另外一个重载方法
		return convertIfNecessary(propertyName, oldValue, newValue, requiredType, TypeDescriptor.valueOf(requiredType));
	}

	/**
	 * Convert the value to the required type (if necessary from a String),
	 * for the specified property.
	 * <p>将指定属性的值转换为所需的类型(如果需要 从 字符串)</p>
	 * <ol>
	 *  <li>如果找不到在preopertyEditorRegistry中requireType对应的属性编辑器,但能拿到ConversionService对象进行对newValue转换为requireType类型对象,并将结果
	 *  返回出去,如果转换失败,会使用conversionAttemptEx保存异常对象</li>
	 *  <li>使用 requireType对应的属性编辑器对 newValue进行转换为【转换后的对象不一定是requiredType类型的对象】【convertedValue】</li>
	 *  <li>convertedValue 不为 null的情况下 :
	 *   <ol>
	 *     <li>如果reqiredType是Object类型,就返回 convertedValue </li>
	 *     <li>如果convertedValue是Collection对象,将 convertedValue 转换为 Collection 类型对象  </li>
	 *     <li>如果convertedValue是 Map类型对象,将 convertedValue 转换为 Map类型对象 </li>
	 *     <li>如果converedValues是数组类型 && convertedValue的数组长度为1,convertedValue引用自己的第一个元素对象</li>
	 *     <li>如果 requiredType 是 String 类型 && convertedValue是原始类型/原始包装类型,将convertedValue转换为字符串转返回出去</li>
	 *     <li>如果 convertedValue 是 String 类型 && convertedValue不是requiredType类型:
	 *      <ol>
	 *         <li> 如果conversionAttemptEx 为 null && requiredType不是接口 && requireType不是枚举类,获取requiredType的接收一个String类型参数的
	 *         构造函数对象,并使用该构造函数传入 convertedValue 实例化对象并返回出去</li>
	 *         <li>如果 requireTyoe是枚举 && convertedValue不是空字符传,就尝试转换String对象为Enum对象convertedValue转换为Number类型对象</li>
	 *      </ol>
	 *     </li>
	 *     <li>如果convertedValue是Number实例 && requiredType是Numnber的实现或子类,将 covertedValue转换为Number类型对象</li>
	 *   </ol>
	 *  </li>
	 *  <li>convertedValue == null && requiredType为Optional类,converdValue就为Optional空对象</li>
	 *  <li>如果 convertedValue 不是 requiredType 的实例 && conversionAttemptEx为null && conversionService不为null && typeDescriptor 不为null,
	 *  将 newValue 转换为 typeDescriptor 对应类型的对象,然后返回出去。</li>
	 *  <li>将convertedValuef返回出去</li>
	 * </ol>
	 * @param propertyName name of the property -- 属性名
	 * @param oldValue the previous value, if available (may be {@code null})
	 *                -- 旧属性值,可以是 null
	 * @param newValue the proposed new value
	 *                 -- 新属性值
	 * @param requiredType the type we must convert to
	 * (or {@code null} if not known, for example in case of a collection element)
	 *                        -- 要装换的类型,必须转换为的类型(如果不知道,例如集合元素,则为null)
	 * @param typeDescriptor the descriptor for the target property or field
	 *                       -- 目标属性 或 字段的描述符
	 * @return the new value, possibly the result of type conversion
	 * 		-- 新值,可能类型转换的结果
	 * @throws IllegalArgumentException if type conversion failed -- 如果类型转换失败
	 */
	@SuppressWarnings("unchecked")
	@Nullable
	public <T> T convertIfNecessary(@Nullable String propertyName, @Nullable Object oldValue, @Nullable Object newValue,
			@Nullable Class<T> requiredType, @Nullable TypeDescriptor typeDescriptor) throws IllegalArgumentException {

		// Custom editor for this type?
		// 自定义编辑这个类型吗?
		//PropertyEditor是属性编辑器的接口,它规定了将外部设置值转换为内部JavaBean属性值的转换接口方法。
		// 为requiredType 和 propertyName找到一个自定义属性编辑器
		PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
		//尝试使用自定义ConversionService转换newValue转换失败后抛出的异常
		ConversionFailedException conversionAttemptEx = null;

		// No custom editor but custom ConversionService specified?
		// 没有自定以编辑器,但自定以 ConversionService 指定了?
		// ConversionService :  一个类型转换的服务接口。这个转换系统的入口。
		//获取 类型转换服务
		ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
		//如果 editor 为null 且 cnversionService 不为null && 新值不为null && 类型描述符不为null
		if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) {
			//将newValue封装成TypeDescriptor对象
			TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
			//如果sourceTypeDesc的对象能被转换成typeDescriptor.
			if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
				try {
					//从conversionService 中找到 sourceTypeDesc,typeDesriptor对于的转换器进行对newValue的转换成符合
					// 	-- typeDesciptor类型的对象,并返回出去
					return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
				}
				catch (ConversionFailedException ex) {
					//捕捉转换失败异常
					// fallback to default conversion logic below
					// 返回到下面的默认转换逻辑
					conversionAttemptEx = ex;
				}
			}
		}

		//默认转换后的值为newValue
		Object convertedValue = newValue;

		// Value not of required type?
		// 值不是必需的类型
		// 如果editor不为null || (requiredType不为null && convertedValue不是requiredType的实例)
		if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
			// 如果 typeDescriptor 不为null && requiredType 不为null && requiredType是Collection的子类或实现 && coventedValue 是 String类型
			if (typeDescriptor != null && requiredType != null && Collection.class.isAssignableFrom(requiredType) &&
					convertedValue instanceof String) {
				//获取该 typeDescriptor的元素TypeDescriptor
				TypeDescriptor elementTypeDesc = typeDescriptor.getElementTypeDescriptor();
				//如果elementTypeDesc不为null
				if (elementTypeDesc != null) {
					//获取elementTypeDesc的类型
					Class<?> elementType = elementTypeDesc.getType();
					//如果elementType是Class类 || elementType 是 Enum 的子类或实现
					if (Class.class == elementType || Enum.class.isAssignableFrom(elementType)) {
						//将convertedValue强转为String,以 逗号 分割 convertedValue 返回空字符串
						convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
					}
				}
			}
			//如果editor为null
			if (editor == null) {
				//找到requiredType的默认编辑器
				editor = findDefaultEditor(requiredType);
			}
			//使用editor将convertedValue转换为requiredType
			convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor);
		}

		//标准转换标记,convertedValue是Collection类型,Map类型,数组类型,可转换成Enum类型的String对象,Number类型并成功进行转换后即为
		// true
		boolean standardConversion = false;

		//如果requriedTyoe不为null
		if (requiredType != null) {
			// Try to apply some standard type conversion rules if appropriate.
			// 如果合适,尝试应用一些标准类型转换规则
			// convertedValue不为null
			if (convertedValue != null) {
				//如果reqiredType是Object类型
				if (Object.class == requiredType) {
					//直接返回conertedValue
					return (T) convertedValue;
				}
				//如果requiredType是数组
				else if (requiredType.isArray()) {
					// Array required -> apply appropriate conversion of elements.
					// 数组所需 -> 应用适当的元素转换
					//如果convertedValue是String的实例 && requiredType的元素类型是Enum的子类或实现
					if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {
						// 将逗号分割的列表(例如 csv 文件中的一行)转换为字符串数组
						convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
					}
					//将 convertedValue 转换为 commpentedType类型数组对象
					return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType());
				}
				//如果convertedValue是Collection对象
				else if (convertedValue instanceof Collection) {
					// Convert elements to target type, if determined.
					// 如果确定,则将元素转换为目标类型
					// 将 convertedValue 转换为 Collection 类型 对象
					convertedValue = convertToTypedCollection(
							(Collection<?>) convertedValue, propertyName, requiredType, typeDescriptor);
					// 更新 standardConversion 标记
					standardConversion = true;
				}
				//如果convertedValue是 Map 对象
				else if (convertedValue instanceof Map) {
					// Convert keys and values to respective target type, if determined.
					// 如果确定了,则将建和值转换为相应的目标类型
					convertedValue = convertToTypedMap(
							(Map<?, ?>) convertedValue, propertyName, requiredType, typeDescriptor);
					// 更新 standardConversion 标记
					standardConversion = true;
				}
				//如果converedValues是数组类型 && convertedValue的数组长度为1
				if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) {
					//获取convertedValue的第一个元素对象
					convertedValue = Array.get(convertedValue, 0);
					//更新 standardConversion 标记
					standardConversion = true;
				}
				//如果 requiredType 是 String 类型 && convertedValue是原始类型/原始包装类型
				if (String.class == requiredType && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) {
					// We can stringify any primitive value...
					// 我们可以 字符串化 任何原始值
					// 将convertedValue转换为字符转返回出去
					return (T) convertedValue.toString();
				}
				//如果 convertedValue 是 String 类型 && convertedValue不是requiredType类型
				else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
					//conversionAttemptEx 为 null 意味着 自定义ConversionService转换newValue转换失败 或者 没有自定义ConversionService
					// 如果conversionAttemptEx 为 null && requiredType不是接口 && requireType不是枚举类
					if (conversionAttemptEx == null && !requiredType.isInterface() && !requiredType.isEnum()) {
						try {
							//获取requiredType的接收一个String类型参数的构造函数对象
							Constructor<T> strCtor = requiredType.getConstructor(String.class);
							//使用 strCtor 构造函数,传入 convertedValue 实例化对象并返回出去
							return BeanUtils.instantiateClass(strCtor, convertedValue);
						}
						catch (NoSuchMethodException ex) {//捕捉 找不到 接收一个String类型参数的构造函数 的异常
							// proceed with field lookup
							// 继续字段查找
							// 如果 当前日志是 跟踪模式
							if (logger.isTraceEnabled()) {
								// 打印日志:没有找到 [requireType类名] 的接收一个String类型参数的构造函数
								logger.trace("No String constructor found on type [" + requiredType.getName() + "]", ex);
							}
						}
						catch (Exception ex) {//捕捉 接收一个String类型参数的构造函数 的异常
							// 如果 当前日志是 调式模式
							if (logger.isDebugEnabled()) {
								// 打印日志:通过 接收一个String类型参数的构造函数 构造[requireType类型]对象 失败
								logger.debug("Construction via String failed for type [" + requiredType.getName() + "]", ex);
							}
						}
					}
					//将convertedValue强转为字符串,并去掉前后的空格
					String trimmedValue = ((String) convertedValue).trim();
					//如果 requireTyoe是枚举 && trimmedValue 是空字符串
					if (requiredType.isEnum() && trimmedValue.isEmpty()) {
						// It's an empty enum identifier: reset the enum value to null.
						// 这个一个空枚举标识符:重置枚举值为null
						return null;
					}
					//尝试转换String对象为Enum对象
					convertedValue = attemptToConvertStringToEnum(requiredType, trimmedValue, convertedValue);
					//更新 standardConversion 标记
					standardConversion = true;
				}
				//如果convertedValue是Number实例 && requiredType是Numnber的实现或子类
				else if (convertedValue instanceof Number && Number.class.isAssignableFrom(requiredType)) {
					//NumberUtils.convertNumberToTargetClass:将convertedValue为requiredType的实例
					convertedValue = NumberUtils.convertNumberToTargetClass(
							(Number) convertedValue, (Class<Number>) requiredType);
					//更新 standardConversion 标记
					standardConversion = true;
				}
			}
			else {// convertedValue == null
				// convertedValue == null
				//如果requiredType为Optional类
				if (requiredType == Optional.class) {
					//将converdValue设置Optional空对象
					convertedValue = Optional.empty();
				}
			}
			//如果 convertedValue 不是 requiredType 的实例
			if (!ClassUtils.isAssignableValue(requiredType, convertedValue)) {
				//conversionAttemptEx:尝试使用自定义ConversionService转换newValue转换失败后抛出的异常
				//conversionAttemptEx不为null
				if (conversionAttemptEx != null) {
					// Original exception from former ConversionService call above...
					// 从前面的 ConversionService 调用的原始异常
					//重新抛出 conversionAttemptEx
					throw conversionAttemptEx;
				}
				//如果conversionService不为null && typeDescriptor 不为null
				else if (conversionService != null && typeDescriptor != null) {
					// ConversionService not tried before, probably custom editor found
					// but editor couldn't produce the required type...
					// ConversionService之前没有尝试过,可能找到了 自定义编辑器,但编辑器不能产生所需的类型
					//获取newValue的类型描述符
					TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
					//如果sourceTypeDesc 的对象能被转换成 typeDescriptor
					if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
						//将 newValue 转换为 typeDescriptor 对应类型的对象
						return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
					}
				}

				// Definitely doesn't match: throw IllegalArgumentException/IllegalStateException
				// 绝对不匹配:抛出  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());
				}
			}
		}
		//conversionAttemptEx:尝试使用自定义ConversionService转换newValue转换失败后抛出的异常
		//conversionAttemptEx不为null
		if (conversionAttemptEx != null) {
			//editor:requiredType 和 propertyName对应一个自定义属性编辑器
			//standardConversion:标准转换标记,convertedValue是Collection类型,Map类型,数组类型,可转换成Enum类型的String对象,Number类型并成功
			// 		进行转换后即为true
			// editor 为 null && 不是标准转换 && 要转换的类型不为null && requiedType不是Object类
			if (editor == null && !standardConversion && requiredType != null && Object.class != requiredType) {
				//重新抛出 conversionAttemptEx
				throw conversionAttemptEx;
			}
			//如果日志级别是调试级别:最初的ConversionService尝试失败————此后被忽略基于PropertyEditor的转换最终成功
			logger.debug("Original ConversionService attempt failed - ignored since " +
					"PropertyEditor based conversion eventually succeeded", conversionAttemptEx);
		}
		//返回转换后的值
		return (T) convertedValue;
	}

	/**
	 * 尝试转换String对象为Enum对象
	 * @param requiredType 要装换的类型,必须转换为的类型
	 * @param trimmedValue 要转换的字符传,要保证其 前后没有空格
	 * @param currentConvertedValue 当前转换后的值
	 */
	private Object attemptToConvertStringToEnum(Class<?> requiredType, String trimmedValue, Object currentConvertedValue) {
		//当前转换后的对象,默认是 currentConvertedValue
		Object convertedValue = currentConvertedValue;

		//如果 requiredType是 Enum 类 && 目标对象不为null
		if (Enum.class == requiredType && this.targetObject != null) {
			// target type is declared as raw enum, treat the trimmed value as <enum.fqn>.FIELD_NAME
			// 目标类型被声明为原始枚举,处理修减值为 <enum.fqn>.FIELD_NAME
			//将trimmedValue的最后一个'.'位置
			int index = trimmedValue.lastIndexOf('.');
			//如果找到'.'的位置
			if (index > - 1) {
				//截取出trimmedValue的index前面的字符传作为枚举类名
				String enumType = trimmedValue.substring(0, index);
				//截取出trimmedValue的index+1后面的字符传为枚举类的属性名
				String fieldName = trimmedValue.substring(index + 1);
				//获取targetObject的类加载器
				ClassLoader cl = this.targetObject.getClass().getClassLoader();
				try {
					//从cl中获取enumType的Class对象
					Class<?> enumValueType = ClassUtils.forName(enumType, cl);
					//获取fieldName 对应  enumValueType 属性对象
					Field enumField = enumValueType.getField(fieldName);
					//取出该属性对象的值作为 convertedValue
					convertedValue = enumField.get(null);
				}
				catch (ClassNotFoundException ex) {//捕捉未找到类异常
					//如果当前日志级别是 跟踪:没法价值 [enumType] 枚举类
					if (logger.isTraceEnabled()) {
						logger.trace("Enum class [" + enumType + "] cannot be loaded", ex);
					}
				}
				catch (Throwable ex) {//捕捉获取枚举对象的所有异常
					//如果当前日志级别是跟踪:属性[fieldName]不是[enumType]枚举类的枚举值
					if (logger.isTraceEnabled()) {
						logger.trace("Field [" + fieldName + "] isn't an enum value for type [" + enumType + "]", ex);
					}
				}
			}
		}
		//如果 convertedValue 与 currentConvertedValue 是同一个对象
		if (convertedValue == currentConvertedValue) {
			// Try field lookup as fallback: for JDK 1.5 enum or custom enum
			// with values defined as static fields. Resulting value still needs
			// to be checked, hence we don't return it right away.
			// 尝试字段查找作为回退:对于JDK 1.5枚举或值定义为静态字段的自定义枚举。结果值仍然需要检查
			// 因此我们不能立即返回它
			try {
				//获取requiredType中trimmedValue属性名的属性对象
				Field enumField = requiredType.getField(trimmedValue);
				//使enumField可访问,并在需要时显示设置enumField的可访问性
				ReflectionUtils.makeAccessible(enumField);
				//取出该enumField的值作为 convertedValue
				convertedValue = enumField.get(null);
			}
			catch (Throwable ex) {//捕捉获取枚举对象的所有异常
				如果当前日志级别是跟踪:属性[fieldName]不是枚举类的枚举值
				if (logger.isTraceEnabled()) {
					logger.trace("Field [" + convertedValue + "] isn't an enum value", ex);
				}
			}
		}
		//返回转换后的值
		return convertedValue;
	}
	/**
	 * Find a default editor for the given type.
	 * <p>找到给定类型的默认编辑器</p>
	 * @param requiredType the type to find an editor for
	 *                     	-- 要为其查找编辑器的类型
	 * @return the corresponding editor, or {@code null} if none
	 * 		-- 对应的编辑器,或 null (如果没有)
	 */
	@Nullable
	private PropertyEditor findDefaultEditor(@Nullable Class<?> requiredType) {
		PropertyEditor editor = null;
		//如果 requireType不为null
		if (requiredType != null) {
			// No custom editor -> check BeanWrapperImpl's default editors.
			// 没有自定义编辑器 -> 检查BeanWrapperImpl 的默认编辑器
			//
			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;
	}

	/**
	 * Convert the value to the required type (if necessary from a String),
	 * using the given property editor.
	 * <p>使用给定的属性编辑器将值转换为所需的类型(如果需要从String)</p>
	 * @param oldValue the previous value, if available (may be {@code null})
	 *                 	-- 前一个值(如果可用)(可以是 null)
	 * @param newValue the proposed new value
	 *                 --  建议的新值
	 * @param requiredType the type we must convert to
	 * (or {@code null} if not known, for example in case of a collection element)
	 *                     -- 必须转换为的类型(如不知道,例如集合元素,则为null)
	 * @param editor the PropertyEditor to use -- 要使用的属性编辑器
	 * @return the new value, possibly the result of type conversion
	 * 		-- 新值,可能是类型转换的结果
	 * @throws IllegalArgumentException if type conversion failed
	 * 	-- 如果类型转换失败
	 */
	@Nullable
	private Object doConvertValue(@Nullable Object oldValue, @Nullable Object newValue,
			@Nullable Class<?> requiredType, @Nullable PropertyEditor editor) {
		//默认转换后的值为newValue
		Object convertedValue = newValue;
		//如果editor不为nll && convertedValue不是字符换
		if (editor != null && !(convertedValue instanceof String)) {
			// Not a String -> use PropertyEditor's setValue.
			// 使用 PropertyEditor 的 setValue
			// With standard PropertyEditors, this will return the very same object;
			// 使用标准的 PropertyEditors,这将返回完全相同的对象
			// we just want to allow special PropertyEditors to override setValue
			// for type conversion from non-String values to the required type.
			// 我们只是想允许特殊的PropertyEditors覆盖setValue来进行从非字符串值所需类型的类型转换
			try {
				//PropertyEditor.setValue:设置属性的值,基本类型以包装类传入(自动装箱);
				//设置editer要编辑的对象为convertedValue
				editor.setValue(convertedValue);
				//重新获取editor的属性值
				Object newConvertedValue = editor.getValue();
				//如果newConvertedValue与convertedValue不是同一个对象
				if (newConvertedValue != convertedValue) {
					//让convertedValue引用该newConvertedValue
					convertedValue = newConvertedValue;
					// Reset PropertyEditor: It already did a proper conversion.
					// 重置 PropertyEditor:它已经做了一个适当的转换
					// Don't use it again for a setAsText call.
					// 不要在调用setAsText时再次使用它
					//PropertyEditor.setAsText:用一个字符串去更新属性的内部值,这个字符串一般从外部属性编辑器传入
					//设置editor为null
					editor = null;
				}
			}
			//捕捉特殊的PropertyEditors覆盖setValue来进行从非字符串值所需类型的类型转换时出现的所有异常
			catch (Exception ex) {
				//如果是debug模式
				if (logger.isDebugEnabled()) {
					//PropertyEditor[editor.getClass().getName()]不能提供 setValue 调用
					logger.debug("PropertyEditor [" + editor.getClass().getName() + "] does not support setValue call", ex);
				}
				// Swallow and proceed.
				// 忍受 并 继续执行
			}
		}
		//默认返回值为转换后的值
		Object returnValue = convertedValue;
		//如果 requireType不为null && requiredType不是数组 && covertedValue 是 String 数组
		if (requiredType != null && !requiredType.isArray() && convertedValue instanceof String[]) {
			// Convert String array to a comma-separated String.
			// 将 字符串数组 转换为 逗号分割的字符串
			// Only applies if no PropertyEditor converted the String array before.
			// 只有在之前没有 PropertyEditor 转换字符串数组是才适用
			// The CSV String will be passed into a PropertyEditor's setAsText method, if any.
			// CSV字符串将被传递到 PropertyEditor的 setAsText方法中(如果有的话)
			//如果是跟踪模式
			if (logger.isTraceEnabled()) {
				//将字符串数组 转换为以逗号分割的字符串
				logger.trace("Converting String array to comma-delimited String [" + convertedValue + "]");
			}
			//将convertedValue转换为以逗号分隔的String(即CSV).
			convertedValue = StringUtils.arrayToCommaDelimitedString((String[]) convertedValue);
		}

		//如果convertedValue是String 实例
		if (convertedValue instanceof String) {
			//如果编辑器不为null
			if (editor != null) {
				// Use PropertyEditor's setAsText in case of a String value.
				// 如果是字符值,请使用PropertyEditord的setAsText
				//如果是跟踪模式
				if (logger.isTraceEnabled()) {
					//转换字符串为[requiredType]适用属性编辑器[editor]
					logger.trace("Converting String to [" + requiredType + "] using property editor [" + editor + "]");
				}
				//将convertedValue强转为String对象
				String newTextValue = (String) convertedValue;
				//使用editor转换newTextValue,并将转换后的值返回出去
				return doConvertTextValue(oldValue, newTextValue, editor);
			}
			//如果requiredType是String类型
			else if (String.class == requiredType) {
				//返回值就是convertedValue
				returnValue = convertedValue;
			}
		}
		//将返回值返回出去
		return returnValue;
	}

	/**
	 * Convert the given text value using the given property editor.
	 * <p>使用给定属性编辑器转换给定的文本值</p>
	 * @param oldValue the previous value, if available (may be {@code null})
	 *                 -- 前一个值(如果可用)(可以是 null )
	 * @param newTextValue the proposed text value
	 *                     -- 建议的文本值
	 * @param editor the PropertyEditor to use
	 *               -- 要使用的属性编辑器
	 * @return the converted value -- 转换后的值
	 */
	private Object doConvertTextValue(@Nullable Object oldValue, String newTextValue, PropertyEditor editor) {
		try {
			//PropertyEditor.setValue:设置属性的值,基本类型以包装类传入(自动装箱)
			//设置editor的属性值为oldValue
			editor.setValue(oldValue);
		}
		catch (Exception ex) {
			//捕捉所有设置属性值时抛出的异常
			//如果是跟踪模式
			if (logger.isDebugEnabled()) {
				//属性编辑器[editor名]不支持调用 setValue
				logger.debug("PropertyEditor [" + editor.getClass().getName() + "] does not support setValue call", ex);
			}
			// Swallow and proceed.
			// 忍受 并 继续处理
		}
		//PropertyEditor.setAsText:用一个字符串去更新属性的内部值,这个字符串一般从外部属性编辑器传入;
		//使用newTextValue更新内部属性值
		editor.setAsText(newTextValue);
		//获取属性值
		return editor.getValue();
	}

	/**
	 * 将input转换为 commpentedType类型数组对象
	 * @param input 要转换的值
	 * @param propertyName 属性名
	 * @param componentType 数组的元素类型
	 * @return 转换的 commpentedType类型数组对象
	 */
	private Object convertToTypedArray(Object input, @Nullable String propertyName, Class<?> componentType) {
		//如果 input是 Collection 实例
		if (input instanceof Collection) {
			// Convert Collection elements to array elements.
			// 将集合元素转换为数组元素
			// 将input强转为Collection对象
			Collection<?> coll = (Collection<?>) input;
			//新建一个元素类型为componentType,长度为coll.size的列表
			Object result = Array.newInstance(componentType, coll.size());
			int i = 0;
			//遍历coll的元素
			for (Iterator<?> it = coll.iterator(); it.hasNext(); i++) {
				//将it的元素转换为componentType类型对象
				Object value = convertIfNecessary(
						buildIndexedPropertyName(propertyName, i), null, it.next(), componentType);
				//将value设置到第i个result元素位置上
				Array.set(result, i, value);
			}
			//返回result
			return result;
		}
		//如果input是数组类型
		else if (input.getClass().isArray()) {
			// Convert array elements, if necessary.
			// 如果需要,转换数组元素
			//如果componentType与input的元素类型相同 && propertyEditorRegistry不包含指定数组/集合元素的自定义编辑器
			if (componentType.equals(input.getClass().getComponentType()) &&
					!this.propertyEditorRegistry.hasCustomEditorForElement(componentType, propertyName)) {
				// 返回input
				return input;
			}
			//获取input的数组长度
			int arrayLength = Array.getLength(input);
			//构建出数组长度为arrayLength,元素类型为componentType的数组
			Object result = Array.newInstance(componentType, arrayLength);
			//遍历result
			for (int i = 0; i < arrayLength; i++) {
				//Array.get(input, i):获取input的第i个元素对象
				//将该值转换为 componentType 对象
				Object value = convertIfNecessary(
						buildIndexedPropertyName(propertyName, i), null, Array.get(input, i), componentType);
				//将value放到result数组的第i个位置里
				Array.set(result, i, value);
			}
			//返回result
			return result;
		}
		else {//这种情况,一般就是input是普通Java对象
			// A plain value: convert it to an array with a single component.
			// 纯值:将其转换为具有单个组件的数组
			// 构建一个长度为1,元素类型为componentType的数组对象
			Object result = Array.newInstance(componentType, 1);
			//将input转换为componentType类型的对象
			Object value = convertIfNecessary(
					buildIndexedPropertyName(propertyName, 0), null, input, componentType);
			//将value设置到result第0个索引位置
			Array.set(result, 0, value);
			//返回result
			return result;
		}
	}

	/**
	 * 将 original 转换为 Collection 类型 对象
	 * @param original 原始对象
	 * @param propertyName 属性名
	 * @param requiredType 要转换的类型
	 * @param typeDescriptor 目标属性 或 字段的描述符
	 */
	@SuppressWarnings("unchecked")
	private Collection<?> convertToTypedCollection(Collection<?> original, @Nullable String propertyName,
			Class<?> requiredType, @Nullable TypeDescriptor typeDescriptor) {
		//如果requiredType不是Collection类型
		if (!Collection.class.isAssignableFrom(requiredType)) {
			//返回original
			return original;
		}
		//collectionType是否是常见的Collection类的标记
		boolean approximable = CollectionFactory.isApproximableCollectionType(requiredType);
		//如果不是常见Collection类 且 不可以 requiredTyped 的实例
		if (!approximable && !canCreateCopy(requiredType)) {
			// 如果 日志级别是 debug, 自定义Collection类型[ 原始对象 类名]不允许创建副本-按原样注入原始集合
			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;
		}
		//如果orginal是requiredType的实例
		boolean originalAllowed = requiredType.isInstance(original);
		//获取 typeDescriptor 的元素类型描述符
		TypeDescriptor elementType = (typeDescriptor != null ? typeDescriptor.getElementTypeDescriptor() : null);
		//如果elementType为null && orginal是requiredType的实例 && propertyEditorRegistry不包含propertyName的null对象的自定义编辑器
		if (elementType == null && originalAllowed &&
				!this.propertyEditorRegistry.hasCustomEditorForElement(null, propertyName)) {
			//返回 原始对象
			return original;
		}
		//original 的迭代器
		Iterator<?> it;
		try {
			//获取 original 的迭代器
			it = original.iterator();
		}
		//捕捉获取迭代器发生的所有异常
		catch (Throwable ex) {
			// 如果 日志级别是 debug模式:不能访问类型为[ original类名]的Collection对象 - 按原样注入原始集合
			if (logger.isDebugEnabled()) {
				logger.debug("Cannot access Collection of type [" + original.getClass().getName() +
						"] - injecting original Collection as-is: " + ex);
			}
			// 返回 原始对象
			return original;
		}
		//转换后的 Collection 对象
		Collection<Object> convertedCopy;
		try {
			//如果requiredType是常见Collection类
			if (approximable) {
				//为original创建最近似的Collection对象,初始容量与 original 保持一致
				convertedCopy = CollectionFactory.createApproximateCollection(original, original.size());
			}
			else {
				//获取requiredType的无参构造函数,然后创建一个实例
				convertedCopy = (Collection<Object>)
						ReflectionUtils.accessibleConstructor(requiredType).newInstance();
			}
		}
		//捕捉 创建 convertedCopy 对象时抛出的异常
		catch (Throwable ex) {
			//如果 日志级别是 debug模式:不能创建 [original 类名] 的 Collection 副本对象 - 按原样注入原始集合
			if (logger.isDebugEnabled()) {
				logger.debug("Cannot create copy of Collection type [" + original.getClass().getName() +
						"] - injecting original Collection as-is: " + ex);
			}
			// 返回 原始对象
			return original;
		}
		//遍历 original 的迭代器
		for (int i = 0; it.hasNext(); i++) {
			//获取元素对象
			Object element = it.next();
			//构建索引形式的属性名。格式:propertyName[i]
			String indexedPropertyName = buildIndexedPropertyName(propertyName, i);
			//将 element 转换为 elementType 类型
			Object convertedElement = convertIfNecessary(indexedPropertyName, null, element,
					(elementType != null ? elementType.getType() : null) , elementType);
			try {
				//将 convertedElement 添加到 convertedCopy 中
				convertedCopy.add(convertedElement);
			}
			catch (Throwable ex) {
				//如果 日志级别是 debug模式: [original 类名] 的 Collection 副本对象 似乎是只读 - 按原样注入原始集合
				if (logger.isDebugEnabled()) {
					logger.debug("Collection type [" + original.getClass().getName() +
							"] seems to be read-only - injecting original Collection as-is: " + ex);
				}
				//返回 原始对象
				return original;
			}
			//更新 originalAllowed:只要 element 与 convertedElement 是同一个对象,就一直为true
			originalAllowed = originalAllowed && (element == convertedElement);
		}
		//如果 originalAllowed 为 true,就返回 original;否则返回 convertedCopy
		return (originalAllowed ? original : convertedCopy);
	}

	/**
	 * 将 original 转换为 Map 类型 对象
	 * @param original 原始对象
	 * @param propertyName 属性名
	 * @param requiredType 要转换的类型
	 * @param typeDescriptor 目标属性 或 字段的描述符
	 */
	@SuppressWarnings("unchecked")
	private Map<?, ?> convertToTypedMap(Map<?, ?> original, @Nullable String propertyName,
			Class<?> requiredType, @Nullable TypeDescriptor typeDescriptor) {
		//如果requiredType不是Collection类型
		if (!Map.class.isAssignableFrom(requiredType)) {
			//返回original
			return original;
		}

		//collectionType是否是常见的Collection类的标记
		boolean approximable = CollectionFactory.isApproximableMapType(requiredType);
		//如果不是常见Collection类 且 不可以 requiredTyped 的实例
		if (!approximable && !canCreateCopy(requiredType)) {
			// 如果 日志级别是 debug, 自定义Map类型[ 原始对象 类名]不允许创建副本-按原样注入原始集合
			if (logger.isDebugEnabled()) {
				logger.debug("Custom Map type [" + original.getClass().getName() +
						"] does not allow for creating a copy - injecting original Map as-is");
			}
			//返回 原始对象
			return original;
		}

		//如果orginal是requiredType的实例
		boolean originalAllowed = requiredType.isInstance(original);
		//如果此 TypeDescriptor是 Map 类型,则获取其Key的类型。如果 typeDescriptor 不是Map类型,将会抛出异常
		TypeDescriptor keyType = (typeDescriptor != null ? typeDescriptor.getMapKeyTypeDescriptor() : null);
		//如果此 TypeDescriptor是 Map 类型,则获取其Value的类型。如果 typeDescriptor 不是Map类型,将会抛出异常
		TypeDescriptor valueType = (typeDescriptor != null ? typeDescriptor.getMapValueTypeDescriptor() : null);
		//如果keyType 为 null  && value 为 null && orginal是requiredType的实例 && propertyEditorRegistry不包含
		// 	propertyName的null对象的自定义编辑器
		if (keyType == null && valueType == null && originalAllowed &&
				!this.propertyEditorRegistry.hasCustomEditorForElement(null, propertyName)) {
			//返回 原始对象
			return original;
		}

		//original 的迭代器
		Iterator<?> it;
		try {
			//获取 original 的迭代器
			it = original.entrySet().iterator();
		}
		//捕捉获取迭代器发生的所有异常
		catch (Throwable ex) {
			// 如果 日志级别是 debug模式:不能访问类型为[ original类名]的Map对象 - 按原样注入原始集合
			if (logger.isDebugEnabled()) {
				logger.debug("Cannot access Map of type [" + original.getClass().getName() +
						"] - injecting original Map as-is: " + ex);
			}
			// 返回 原始对象
			return original;
		}

		//转换后的 Collection 对象
		Map<Object, Object> convertedCopy;
		try {
			//如果requiredType是常见Collection类
			if (approximable) {
				//为original创建最近似的Collection对象,初始容量与 original 保持一致
				convertedCopy = CollectionFactory.createApproximateMap(original, original.size());
			}
			else {
				//获取requiredType的无参构造函数,然后创建一个实例
				convertedCopy = (Map<Object, Object>)
						ReflectionUtils.accessibleConstructor(requiredType).newInstance();
			}
		}
		//捕捉 创建 convertedCopy 对象时抛出的异常
		catch (Throwable ex) {
			//如果 日志级别是 debug模式:不能创建 [original 类名] 的 Map 副本对象 - 按原样注入原始集合
			if (logger.isDebugEnabled()) {
				logger.debug("Cannot create copy of Map type [" + original.getClass().getName() +
						"] - injecting original Map as-is: " + ex);
			}
			// 返回 原始对象
			return original;
		}

		//遍历 original 的迭代器
		while (it.hasNext()) {
			//获取元素对象
			Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
			//获取entry的key对象
			Object key = entry.getKey();
			//获取entry的value对象
			Object value = entry.getValue();
			//构建键名形式的属性名。格式:propertyName[key]
			String keyedPropertyName = buildKeyedPropertyName(propertyName, key);
			//将 key 转换为 keyType 类型
			Object convertedKey = convertIfNecessary(keyedPropertyName, null, key,
					(keyType != null ? keyType.getType() : null), keyType);
			//将 value 转换为 valueType 类型
			Object convertedValue = convertIfNecessary(keyedPropertyName, null, value,
					(valueType!= null ? valueType.getType() : null), valueType);
			try {
				//将 convertedKey,convertedValue 添加到 convertedCopy 中
				convertedCopy.put(convertedKey, convertedValue);
			}
			catch (Throwable ex) {
				//如果 日志级别是 debug模式: [original 类名] 的 Collection 副本对象 似乎是只读 - 按原样注入原始集合
				if (logger.isDebugEnabled()) {
					logger.debug("Map type [" + original.getClass().getName() +
							"] seems to be read-only - injecting original Map as-is: " + ex);
				}
				//返回 原始对象
				return original;
			}
			//更新 originalAllowed:只要 element 与 convertedKey 是同一个对象 && value 与 convertedValue 是同一个对象 ,就
			// 		一直为true
			originalAllowed = originalAllowed && (key == convertedKey) && (value == convertedValue);
		}
		//如果 originalAllowed 为 true,就返回 original;否则返回 convertedCopy
		return (originalAllowed ? original : convertedCopy);
	}

	/**
	 * 构建索引形式的属性名。格式:propertyName[index]
	 * @param propertyName 属性名
	 * @param index 索引
	 * @return 索引形式的属性名;如果propertyName为null,返回null
	 */
	@Nullable
	private String buildIndexedPropertyName(@Nullable String propertyName, int index) {
		return (propertyName != null ?
				propertyName + PropertyAccessor.PROPERTY_KEY_PREFIX + index + PropertyAccessor.PROPERTY_KEY_SUFFIX :
				null);
	}

	/**
	 * 构建键名形式的属性名。格式:propertyName[key]
	 * @param propertyName 属性名
	 * @param key 键名
	 * @return 索引形式的属性名;如果propertyName为null,返回null
	 */
	@Nullable
	private String buildKeyedPropertyName(@Nullable String propertyName, Object key) {
		return (propertyName != null ?
				propertyName + PropertyAccessor.PROPERTY_KEY_PREFIX + key + PropertyAccessor.PROPERTY_KEY_SUFFIX :
				null);
	}

	/**
	 * 是否可以 requiredTyped 的实例
	 * @param requiredType 请求类型
	 */
	private boolean canCreateCopy(Class<?> requiredType) {
		//如果 requiredType不是接口 && requiredType不是抽象 && requiredType是Public && requiredType是无参构造方法 就返回true
		return (!requiredType.isInterface() && !Modifier.isAbstract(requiredType.getModifiers()) &&
				Modifier.isPublic(requiredType.getModifiers()) && ClassUtils.hasConstructor(requiredType));
	}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值