【框架专题】——管理型容器——SpringIOC源码——数据封装层——BeanWrapper与TypeConverter

原文章:https://blog.csdn.net/qq_41907991/article/details/105214244
作者对此进行整理并发布

BeanWrapper——接口概述

BeanWrapper是已经将bean创建好了以后,需要用一个包装层来表示这个bean以便于更好的bean之间的通讯,而Beandefinition 是创建前需要用到的信息

BeanWrapper——根接口

PropertyDescriptor:属性描述符,能够描述javaBean中的属性,通过属性描述符我们能知道这个属性的类型,获取到操纵属性的方法(getter/setter)

public interface BeanWrapper extends ConfigurablePropertyAccessor {
	void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);
	int getAutoGrowCollectionLimit();
	
	Object getWrappedInstance();// 获取包装的Bean
	Class<?> getWrappedClass();// 获取包装的Bean的class

	PropertyDescriptor[] getPropertyDescriptors();// 获取所有属性的属性描述符
	PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;// 获取指定属性的属性描述符
}

BeanWrapperImpl——实现类

public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements BeanWrapper {
	// 缓存内省的结果,BeanWrapperImpl就是通过这个对象来完成对包装的Bean的属性的控制
	@Nullable
	private CachedIntrospectionResults cachedIntrospectionResults;
    ......       
   	public void setBeanInstance(Object object) {
		this.wrappedObject = object;
		this.rootObject = object;
        // 实际进行类型转换的对象:typeConverterDelegate
		this.typeConverterDelegate = new TypeConverterDelegate(this, this.wrappedObject);
		setIntrospectionClass(object.getClass());
	}
    ......
    // 最终调用的就是CachedIntrospectionResults的forClass方法进行内省并缓存,底层调用的就是java的内省机制
    private CachedIntrospectionResults getCachedIntrospectionResults() {
        if (this.cachedIntrospectionResults == null) {
            this.cachedIntrospectionResults = CachedIntrospectionResults.forClass(getWrappedClass());
        }
        return this.cachedIntrospectionResults;
    }
   .......
       // 最终进行类型转换的方法
       private Object convertIfNecessary(@Nullable String propertyName, @Nullable Object oldValue,
                                         @Nullable Object newValue, @Nullable Class<?> requiredType, @Nullable TypeDescriptor td)
       throws TypeMismatchException {

       Assert.state(this.typeConverterDelegate != null, "No TypeConverterDelegate");
       try {
           // 可以看到,最后就是调用typeConverterDelegate来进行类型转换
           return this.typeConverterDelegate.convertIfNecessary(propertyName, oldValue, newValue, requiredType, td);
       }
       ......
   }
}

BeanWrapperImpl——父类分析

在这里插入图片描述

AbstractNestablePropertyAccessor

定义和保存的包装的bean以及实现属性访问的具体实现
在这里插入图片描述

AbstractPropertyAccessor

主要定义流程
在这里插入图片描述

TypeConverterSupport

在这里插入图片描述

内置了一个TypeConverterDelegate实现类型转化的具体实现

PropertyEditorRegistrySupport

这个类最大的作用在于管理PropertyEditor,添加了很多的默认的PropertyEditor。在PropertyEditorRegistry的基础上做了进一步的扩展,提供的还是属性编辑器注册的功能。
在这里插入图片描述
可以看得出内置了很多Map,都是用Class作为key去拿出

BeanWrapperImpl——类型转化实现

TypeConverterDelegate

在这里插入图片描述

class TypeConverterDelegate {
	private final PropertyEditorRegistrySupport propertyEditorRegistry;
	@Nullable
	private final Object targetObject;
	public <T> T convertIfNecessary(@Nullable String propertyName, @Nullable Object oldValue, @Nullable Object newValue,
			@Nullable Class<T> requiredType, @Nullable TypeDescriptor typeDescriptor) throws IllegalArgumentException {
		// 查看是否为当前这个类型配置了定制的PropertyEditor
		PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
		ConversionFailedException conversionAttemptEx = null;
		// 获取当前容器中的类型转换业务类
		ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
        // 在这里可以看出,Spring底层在进行类型转换时有两套机制
        // 1.首选的是采用PropertyEditor
        // 2.在没有配置PropertyEditor的情况下,会采用conversionService
		if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) {
			TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
			if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
				try {
                    // 通过conversionService进行类型转换
					return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
				}
				catch (ConversionFailedException ex) {
					// fallback to default conversion logic below
					conversionAttemptEx = ex;
				}
			}
		}
		Object convertedValue = newValue;
		// 配置了定制的属性编辑器,采用PropertyEditor进行属性转换
		if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
			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)) {
						convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
					}
				}
			}
			if (editor == null) {
                // 没有配置定制的属性编辑器,采用默认的属性编辑器
				editor = findDefaultEditor(requiredType);
			}
            // 采用属性编辑器进行转换,需要注意的是,默认情况下PropertyEditor只会对String类型的值进行类型转换
			convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor);
		}
        // .....
		return (T) convertedValue;
	}
	
}

从上面的代码中我们可以知道,Spring在实现类型转换时,有两套机制,第一套机制依赖于PropertyEditor,第二套机制依赖于ConversionService。关于属性编辑器PropertyEditor我们之前已经介绍过了,主要进行的是String到Object的转换,正因为如此,属性编辑器进行类型转换有很大的局限性,所以Spring又推出了一套ConversionService的体系。

Spring内置的PropertyEditor

在这里插入图片描述

ConversionService(待完善)

在这里插入图片描述
Converter

package org.springframework.core.convert.converter;

public interface Converter<S, T> {// 将一个S=>数据转换>T类型
    T convert(S source);
}

ConverterFactory

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

}

GenericConverter
ConversionService+ConverterRegistry=>ConfigurableConversionService
GenericConversionService/DefaultConversionService

总结

在这里插入图片描述

你可能感兴趣的:(Java框架源码,java,spring)