【管理型框架】SpringIOC——数据处理篇(PropertyEditor/ConversionService/TypeConverter/BeanWrapperImpl/Formatting)

数据转化基础——字符转对象——PropertyEditor

用于字符串到其它对象的转换,有局限性

PropertyEditor——内置实现

【管理型框架】SpringIOC——数据处理篇(PropertyEditor/ConversionService/TypeConverter/BeanWrapperImpl/Formatting)_第1张图片

PropertyEditor——自定义

【配置类】

@Configuration
public class CustomPropertyEditorConfiguration {
     
    @Bean
    public CustomEditorConfigurer customEditorConfigurer(){
     
        CustomEditorConfigurer customEditorConfigurer = new CustomEditorConfigurer();
        /**
         * 如果类型是User,则调用value解析器PointPropertEditor完成注入
         */
        Map<Class<?>,  Class<? extends PropertyEditor>> customEditorMap = new HashMap<>();
        customEditorMap.put(User.class, PointPropertEditor.class);
        customEditorConfigurer.setCustomEditors(customEditorMap);
        return customEditorConfigurer ;
    }
    static class PointPropertEditor  extends PropertyEditorSupport {
     
        /**
         * 接收value的注解值text
         * @param text
         * @throws IllegalArgumentException
         */
        @Override
        public void setAsText(String text) throws IllegalArgumentException {
     
            /**
             * 创建一个对象,以value注解内的值作为参数给这个对象
             */
            User point = new User();
            point.setUsername(text);
            /**
             * 将这个对象注入到指定属性
             */
            setValue(point);
        }
    }
}
@Data
public class User {
     
   private String username;
   private String password;
}

【测试1】

@Data
@Component("propertyValueDemo01")
public class PropertyValueDemo01 {
     
    @Value("111111")
    private User user;
    @PostConstruct
    public void init(){
     
        System.out.println(user);
    }
}

结果

在这里插入图片描述

value注解是什么,值就是什么

【测试2】

@Data
@Component("propertyValueDemo01")
public class PropertyValueDemo01 {
     
    @Value("#{propertyValueDemo02.value}")
    private User user;
    @PostConstruct
    public void init(){
     
        System.out.println(user);
    }
}
@Data
@Component("propertyValueDemo02")
public class PropertyValueDemo02 {
     
   String value="propertyValueDemo02";
}

结果

用spel拿到的值是什么,参数就是什么

在这里插入图片描述

PropertyEditor——父类链条

PropertyEditorRegistry

封装用于注册JavaBeans PropertyEditors的方法。这是PropertyEditorRegistrar操作的中央接口。

public interface PropertyEditorRegistry {
     

  void registerCustomEditor(Class<?> requiredType, PropertyEditor propertyEditor);
  /**每个属性路径只支持一个已注册的自定义编辑器。对于集合/数组,不要同时为集合/数组和相同属性上的每个元素注册一个编辑器。例如,如果您想为“items[n].quantity”注册一个编辑器(对于所有值n),您应该使用“items.quantity”作为这个方法“propertyPath”参数的值。**/
  // propertyPath:属性的路径(名称或嵌套路径),如果为给定类型的所有属性注册一个编辑器,则为null
void registerCustomEditor(Class<?> requiredType, String propertyPath, PropertyEditor propertyEditor);

PropertyEditor findCustomEditor(Class<?> requiredType, String propertyPath);

}

PropertyEditorRegistrySupport实现

PropertyEditorRegistry接口的默认实现,并且提供了默认editors和自定义editors的管理,主要作为服务BeanWrapperImpl的基类

public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
     
  	// ......
	private ConversionService conversionService;
	private boolean defaultEditorsActive = false;
	private boolean configValueEditorsActive = false;
	private Map<Class<?>, PropertyEditor> defaultEditors;
	private Map<Class<?>, PropertyEditor> overriddenDefaultEditors;
	private Map<Class<?>, PropertyEditor> customEditors;
	private Map<String, CustomEditorHolder> customEditorsForPath;
  	// ......
}

CustomEditorConfigurer

该类是BeanFactoryPostProcessor(BFPP类)的实现者,该类允许自定义属性编辑器的方便注册

PropertyEditorRegistrar

需要在几种不同的情况下使用同一组属性编辑器时,这一点特别有用:编写相应的注册器并在每种情况下重用它

public interface PropertyEditorRegistrar {
     
  // 该方法传入registry并添加自定义的PropertyEditor,一般情况下传入的registry是BeanWrapperImpl的实体,所以就等于将自定义的PropertyEditor注入到BeanWrapperImpl里面
void registerCustomEditors(PropertyEditorRegistry registry);
}

数据转化基础——对象转对象——ConversionService

数据格式化——内置converter

1)标量转换器
【管理型框架】SpringIOC——数据处理篇(PropertyEditor/ConversionService/TypeConverter/BeanWrapperImpl/Formatting)_第2张图片
2)集合、数组相关转换器
【管理型框架】SpringIOC——数据处理篇(PropertyEditor/ConversionService/TypeConverter/BeanWrapperImpl/Formatting)_第3张图片

自定义ConversionService

实体类

用@value直接读取一个对象,然后调用convert转化成stirng

@Component
public class ConvertDemo01 {
     
    @Value("#{convertDemo02.user}")
    String data;
    @PostConstruct
    public void init(){
     
        System.out.println(data);
    }
}
@Data
@Component
public class ConvertDemo02 {
     
    User user=new User("ConvertDemo02————username",",ConvertDemo02————password");
}

User转化String的类的转化器

public class UserToStringConvert implements Converter<User, String> {
     
    @Override
    public String convert(User source) {
     
        return source.getPassword();
    }

}

添加转化器

@Configuration
public class MyConversionServiceFactoryBean {
     
    @Bean
    public ConversionServiceFactoryBean conversionService(){
     
        ConversionServiceFactoryBean conversionServiceFactoryBean=new ConversionServiceFactoryBean();
        Set<Converter> set=new HashSet<>();
        set.add(new UserToStringConvert());
        conversionServiceFactoryBean.setConverters(set);
        return conversionServiceFactoryBean;
    }
}

结果
在这里插入图片描述

ConversionService场景

例如,在application.yml定义了这个字符串;

原有的json字符串

com:
  userList: '[
      {
     "id":1,"name":"张三","age":12},
      {
     "id":1,"name":"张三","age":12},
      {
     "id":1,"name":"张三","age":12},
      {
     "id":1,"name":"张三","age":12}
   ]'

string转成List 类型

@Data
@Configuration
public class ConvertService_Test01 {
     
    @Value("${com.userList}")
    List<User> user;
    @PostConstruct
    public void  init(){
     
        System.out.println(user);
    }

}
@Data
public class User {
     
    Long id;
    String name;
    int age;
}

添加转化器

@Configuration
public class MyConversionServiceFactoryBean {
     
    static class StrToListConvert implements Converter<String, List<User>>{
     
        public List<User> convert(String source) {
     
            List<User> users = JackSonUtils.jsonToList(source, User.class);
            return users;
        }
    }
    @Bean
    public ConversionServiceFactoryBean conversionService(){
     
        ConversionServiceFactoryBean conversionServiceFactoryBean=new ConversionServiceFactoryBean();
        Set<Converter> set=new HashSet<>();
        set.add(new StrToListConvert());
        conversionServiceFactoryBean.setConverters(set);
        return conversionServiceFactoryBean;
    }
}

结果
【管理型框架】SpringIOC——数据处理篇(PropertyEditor/ConversionService/TypeConverter/BeanWrapperImpl/Formatting)_第4张图片

Spring中的转化器,可以在mvc框架中注解也调用转化器来支持其他注解,非常多的应用场景

ConversionService链条

【管理型框架】SpringIOC——数据处理篇(PropertyEditor/ConversionService/TypeConverter/BeanWrapperImpl/Formatting)_第5张图片
Converter

将某个S类型转化成T类型

package org.springframework.core.convert.converter;

public interface Converter<S, T> {
     
    T convert(S source);
}

ConverterFactory

批量转化,一个类型转化成多个类型

public interface ConverterFactory<S, R> {
     
	<T extends R> Converter<S, T> getConverter(Class<T> targetType);
}

GenericConverter

用于在两种或更多种类型之间转换的通用转换器接口

ConversionService+ConverterRegistry=>ConfigurableConversionService
GenericConversionService/DefaultConversionService

数据转化合成——TypeConverter

整合以上两个convertService还有PropertyEditor的调用实现,Spring只能看到TypeConverter,而具体调用哪个实现数据转化,由TypeConverter内部决定

TypeConverter接口

/**
 * 定义类型转换方法的接口。通常(但不一定)与PropertyEditorRegistry接口一起实现
 * 通常接口TypeConverter的实现是基于非线程安全的PropertyEditors类,因此也不是线程安全的
 */
public interface TypeConverter {
     

    /**
     * 将参数中的value转换成requiredType类型
     * 从String到任何类型的转换通常使用PropertyEditor类的setAsText方法或ConversionService中的Spring Converter
     */
    <T> T convertIfNecessary(Object value, Class<T> requiredType) throws TypeMismatchException;

    /**
     * 意义同上,增加了作为转换目标的方法参数,主要用于分析泛型类型,可能是null
     */
    <T> T convertIfNecessary(Object value, Class<T> requiredType, MethodParameter methodParam) throws TypeMismatchException;

    /**
     * 意义同上,增加了转换目标的反射field
     */
    <T> T convertIfNecessary(Object value, Class<T> requiredType, Field field) throws TypeMismatchException;
}

TypeConverterSupport抽象类

TypeConverter的基本实现类

public abstract class TypeConverterSupport extends PropertyEditorRegistrySupport implements TypeConverter {
     
  // 委托给TypeConverterDelegate来转换
TypeConverterDelegate typeConverterDelegate;

@Override
public <T> T convertIfNecessary(Object value, Class<T> requiredType) throws TypeMismatchException {
     
    return doConvert(value, requiredType, null, null);
}

@Override
public <T> T convertIfNecessary(Object value, Class<T> requiredType, MethodParameter methodParam) throws TypeMismatchException {
     
    return doConvert(value, requiredType, methodParam, null);
}

@Override
public <T> T convertIfNecessary(Object value, Class<T> requiredType, Field field) throws TypeMismatchException {
     
    return doConvert(value, requiredType, null, field);
}

private <T> T doConvert(Object value, Class<T> requiredType, MethodParameter methodParam, Field field) throws TypeMismatchException {
     
      if (field != null) {
     
          return this.typeConverterDelegate.convertIfNecessary(value, requiredType, field);
        } else {
     
          return this.typeConverterDelegate.convertIfNecessary(value, requiredType, methodParam);
        }
}

}

TypeConverterDelegate类

类型转换的委托类,所有类型转换的工作都由该类完成,即将属性转换为其他类型的Spring内部使用方法(内部实现: 先使用PropertyEditor转换器器转换,如果没找到对应的转换器器,会⽤ConversionService来进⾏行行对象转换。)

class TypeConverterDelegate {
     
    private final PropertyEditorRegistrySupport propertyEditorRegistry;
    private final Object targetObject;
    // ......
}

数据转化时机(1)——doResolveDependency

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
     
		public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
     
		
		try {
     
			/*
			  @value注解类型的解析
			  如果是则直接调用TypeConverter返回出现
			 */
			Class<?> type = descriptor.getDependencyType();
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			if (value != null) {
     
				if (value instanceof String) {
     
					String strVal = resolveEmbeddedValue((String) value);
					BeanDefinition bd = (beanName != null && containsBean(beanName) ?
							getMergedBeanDefinition(beanName) : null);
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
				try {
     
					return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
				}
				catch (UnsupportedOperationException ex) {
     
					return (descriptor.getField() != null ?
							converter.convertIfNecessary(value, type, descriptor.getField()) :
							converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
				}
			}
            /*
			  @解析集合类型
			 */
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
     
				return multipleBeans;
			}
            /*
			  找到匹配的bean
			 */
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			String autowiredBeanName;
			Object instanceCandidate;

			if (matchingBeans.size() > 1) {
     
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
     
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
     
						return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
					}
					else {
     
						return null;
					}
				}
				instanceCandidate = matchingBeans.get(autowiredBeanName);
			}
			else {
     
				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			if (autowiredBeanNames != null) {
     
				autowiredBeanNames.add(autowiredBeanName);
			}
			if (instanceCandidate instanceof Class) {
     
				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
			}
			Object result = instanceCandidate;
			if (result instanceof NullBean) {
     
				if (isRequired(descriptor)) {
     
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				result = null;
			}
			if (!ClassUtils.isAssignableValue(type, result)) {
     
				throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
			}
			return result;
		}
	}
}

数据转化时机(2)——BeanDefinitionValueResolver

BeanDefinitionValueResolver专用于去解析定义信息中value值,他内置了TypeConverter

ValueResolver——数据结构

class BeanDefinitionValueResolver {
     
  /*
    构造器中传入了typeConverter
   */
	public BeanDefinitionValueResolver(
			AbstractBeanFactory beanFactory, String beanName, BeanDefinition beanDefinition, TypeConverter typeConverter) {
     

		this.beanFactory = beanFactory;
		this.beanName = beanName;
		this.beanDefinition = beanDefinition;
		this.typeConverter = typeConverter;
	}
	/*
      对外暴露的方法
   */
	public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
     
		/*
		  以下就是针对不同的类型做了处理
		 */
		if (value instanceof RuntimeBeanReference) {
     
			RuntimeBeanReference ref = (RuntimeBeanReference) value;
			return resolveReference(argName, ref);
		}
		else if (value instanceof RuntimeBeanNameReference) {
     
			String refName = ((RuntimeBeanNameReference) value).getBeanName();
			refName = String.valueOf(doEvaluate(refName));
			if (!this.beanFactory.containsBean(refName)) {
     
				throw new BeanDefinitionStoreException(
						"Invalid bean name '" + refName + "' in bean reference for " + argName);
			}
			return refName;
		}
		else if (value instanceof BeanDefinitionHolder) {
     
			BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
			return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
		}
		else if (value instanceof BeanDefinition) {
     
			BeanDefinition bd = (BeanDefinition) value;
			String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
					ObjectUtils.getIdentityHexString(bd);
			return resolveInnerBean(argName, innerBeanName, bd);
		}
		else if (value instanceof ManagedArray) {
     
			ManagedArray array = (ManagedArray) value;
			Class<?> elementType = array.resolvedElementType;
			if (elementType == null) {
     
				String elementTypeName = array.getElementTypeName();
				if (StringUtils.hasText(elementTypeName)) {
     
					try {
     
						elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
						array.resolvedElementType = elementType;
					}
					catch (Throwable ex) {
     
						throw new BeanCreationException(
								this.beanDefinition.getResourceDescription(), this.beanName,
								"Error resolving array type for " + argName, ex);
					}
				}
				else {
     
					elementType = Object.class;
				}
			}
			return resolveManagedArray(argName, (List<?>) value, elementType);
		}
		else if (value instanceof ManagedList) {
     
			return resolveManagedList(argName, (List<?>) value);
		}
		else if (value instanceof ManagedSet) {
     
			return resolveManagedSet(argName, (Set<?>) value);
		}
		else if (value instanceof ManagedMap) {
     
			return resolveManagedMap(argName, (Map<?, ?>) value);
		}
		else if (value instanceof ManagedProperties) {
     
			Properties original = (Properties) value;
			Properties copy = new Properties();
			original.forEach((propKey, propValue) -> {
     
				if (propKey instanceof TypedStringValue) {
     
					propKey = evaluate((TypedStringValue) propKey);
				}
				if (propValue instanceof TypedStringValue) {
     
					propValue = evaluate((TypedStringValue) propValue);
				}
				if (propKey == null || propValue == null) {
     
					throw new BeanCreationException(
							this.beanDefinition.getResourceDescription(), this.beanName,
							"Error converting Properties key/value pair for " + argName + ": resolved to null");
				}
				copy.put(propKey, propValue);
			});
			return copy;
		}
		else if (value instanceof TypedStringValue) {
     
			TypedStringValue typedStringValue = (TypedStringValue) value;
			Object valueObject = evaluate(typedStringValue);
			try {
     
				Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
				if (resolvedTargetType != null) {
     
					return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
				}
				else {
     
					return valueObject;
				}
			}
			catch (Throwable ex) {
     
				throw new BeanCreationException(
						this.beanDefinition.getResourceDescription(), this.beanName,
						"Error converting typed String value for " + argName, ex);
			}
		}
		else if (value instanceof NullBean) {
     
			return null;
		}
		else {
     
			return evaluate(value);
		}
	}
}

ValueResolver——调用A

xml的value值最后进入applyPropertyValues,然后进行类型转化

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
		implements AutowireCapableBeanFactory {
     
		protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
     
		//……
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
		//……
		if (pvs != null) {
     
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}
}
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
     
        /*
          获取类型转化器
         */
		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
     
			converter = bw;
		}
		/*
		  将类型转化器嵌入到value解析器中(主要是xml中指定的value值或者@value注解的会进入这里)
		 */
		BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
       /*
        * 下面就是实际处理
        */
		List<PropertyValue> deepCopy = new ArrayList<>(original.size());
		boolean resolveNecessary = false;
		for (PropertyValue pv : original) {
     
			if (pv.isConverted()) {
     
				deepCopy.add(pv);
			}
			else {
     
				String propertyName = pv.getName();
				Object originalValue = pv.getValue();
				if (originalValue == AutowiredPropertyMarker.INSTANCE) {
     
					Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
					if (writeMethod == null) {
     
						throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
					}
					originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
				}
				Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
				Object convertedValue = resolvedValue;
				boolean convertible = bw.isWritableProperty(propertyName) &&
						!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
				if (convertible) {
     
					convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
				}
				if (resolvedValue == originalValue) {
     
					if (convertible) {
     
						pv.setConvertedValue(convertedValue);
					}
					deepCopy.add(pv);
				}
				else if (convertible && originalValue instanceof TypedStringValue &&
						!((TypedStringValue) originalValue).isDynamic() &&
						!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
     
					pv.setConvertedValue(convertedValue);
					deepCopy.add(pv);
				}
				else {
     
					resolveNecessary = true;
					deepCopy.add(new PropertyValue(pv, convertedValue));
				}
			}
		}

	}

ValueResolver——调用B

构造器的参数解析会用到这个

class ConstructorResolver {
     
		private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
			ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
     

		TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
		TypeConverter converter = (customConverter != null ? customConverter : bw);
		BeanDefinitionValueResolver valueResolver =
				new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);

		int minNrOfArgs = cargs.getArgumentCount();

		for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
     
			int index = entry.getKey();
			if (index < 0) {
     
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Invalid constructor argument index: " + index);
			}
			if (index > minNrOfArgs) {
     
				minNrOfArgs = index + 1;
			}
			ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
			if (valueHolder.isConverted()) {
     
				resolvedValues.addIndexedArgumentValue(index, valueHolder);
			}
			else {
     
				Object resolvedValue =
						valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
				ConstructorArgumentValues.ValueHolder resolvedValueHolder =
						new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
				resolvedValueHolder.setSource(valueHolder);
				resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
			}
		}

		for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
     
			if (valueHolder.isConverted()) {
     
				resolvedValues.addGenericArgumentValue(valueHolder);
			}
			else {
     
				Object resolvedValue =
						valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
				ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(
						resolvedValue, valueHolder.getType(), valueHolder.getName());
				resolvedValueHolder.setSource(valueHolder);
				resolvedValues.addGenericArgumentValue(resolvedValueHolder);
			}
		}

		return minNrOfArgs;
	}
}

数据转化时机(3)——BeanWrapperImpl

BeanWrapperImpl在applyPropertyValues用到了类型转化器,所以我们题外多分享一下这个实现类

BeanWrapper——接口概述

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

BeanWrapper——根接口

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

public interface BeanWrapper extends ConfigurablePropertyAccessor {
     
	void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);
	int getAutoGrowCollectionLimit();
	/*
	  获取包装的Bean
	 */
	Object getWrappedInstance();
	/*
	  获取包装的Bean的class
	 */
	Class<?> getWrappedClass();
    /*
      获取所有属性的属性描述符
     */
	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——父类分析

【管理型框架】SpringIOC——数据处理篇(PropertyEditor/ConversionService/TypeConverter/BeanWrapperImpl/Formatting)_第6张图片

AbstractNestablePropertyAccessor——属性访问的实现

定义和保存的包装的bean以及实现属性访问的具体实现
【管理型框架】SpringIOC——数据处理篇(PropertyEditor/ConversionService/TypeConverter/BeanWrapperImpl/Formatting)_第7张图片

AbstractPropertyAccessor——主要定义流程

【管理型框架】SpringIOC——数据处理篇(PropertyEditor/ConversionService/TypeConverter/BeanWrapperImpl/Formatting)_第8张图片

TypeConverterSupport

【管理型框架】SpringIOC——数据处理篇(PropertyEditor/ConversionService/TypeConverter/BeanWrapperImpl/Formatting)_第9张图片

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

PropertyEditorRegistrySupport

这个类最大的作用在于管理PropertyEditor,添加了很多的默认的PropertyEditor。在PropertyEditorRegistry的基础上做了进一步的扩展,提供的还是属性编辑器注册的功能。
【管理型框架】SpringIOC——数据处理篇(PropertyEditor/ConversionService/TypeConverter/BeanWrapperImpl/Formatting)_第10张图片
可以看得出内置了很多Map,都是用Class作为key去拿出

BeanWrapperImpl——类型转化实现

TypeConverterDelegate

【管理型框架】SpringIOC——数据处理篇(PropertyEditor/ConversionService/TypeConverter/BeanWrapperImpl/Formatting)_第11张图片

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 {
     
		
       /*
          利用propertyEditorRegistry
          找到这个类型配置了定制的PropertyEditor或者conversionService 
        */
		PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
		ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
         /*
          利用conversionService转化
          没有配置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的体系。
【管理型框架】SpringIOC——数据处理篇(PropertyEditor/ConversionService/TypeConverter/BeanWrapperImpl/Formatting)_第12张图片

数据转化时机(4)——Formatter

Formatter是用于数据格式化的一个类型,那么他也是经由convertservice去调用的

数据格式化——转化嵌入——FormattingConversionService

public class FormattingConversionService extends GenericConversionService
		implements FormatterRegistry, EmbeddedValueResolverAware {
     
	@Override
	public void addFormatterForFieldType(Class<?> fieldType, Formatter<?> formatter) {
     
		addConverter(new PrinterConverter(fieldType, formatter, this));
		addConverter(new ParserConverter(fieldType, formatter, this));
	}

	@Override
	public void addFormatterForFieldType(Class<?> fieldType, Printer<?> printer, Parser<?> parser) {
     
		addConverter(new PrinterConverter(fieldType, printer, this));
		addConverter(new ParserConverter(fieldType, parser, this));
	}
		public void addFormatterForFieldAnnotation(AnnotationFormatterFactory<? extends Annotation> annotationFormatterFactory) {
     
		Class<? extends Annotation> annotationType = getAnnotationType(annotationFormatterFactory);
		if (this.embeddedValueResolver != null && annotationFormatterFactory instanceof EmbeddedValueResolverAware) {
     
			((EmbeddedValueResolverAware) annotationFormatterFactory).setEmbeddedValueResolver(this.embeddedValueResolver);
		}
		Set<Class<?>> fieldTypes = annotationFormatterFactory.getFieldTypes();
		for (Class<?> fieldType : fieldTypes) {
     
			addConverter(new AnnotationPrinterConverter(annotationType, annotationFormatterFactory, fieldType));
			addConverter(new AnnotationParserConverter(annotationType, annotationFormatterFactory, fieldType));
		}
	}
}

在这里插入图片描述

数据格式化——内置接口

Printer接口

用于将Object转成规范格式的String

public interface Printer<T> {
     
    String print(T fieldValue, Locale locale);
}

Parser接口

用于将规范格式的String转化成Object

public interface Parser<T> {
     
    T parse(String clientValue, Locale locale) throws ParseException;
}

Formatter接口

public interface Formatter<T> extends Printer<T>, Parser<T> {
     
}

数据格式化——内置实现

【管理型框架】SpringIOC——数据处理篇(PropertyEditor/ConversionService/TypeConverter/BeanWrapperImpl/Formatting)_第13张图片

数据格式化——注解驱动测试

直接调用

public class Main {
     
	public static void main(String[] args) throws Exception {
     
		DateFormatter dateFormatter = new DateFormatter();
		dateFormatter.setIso(DateTimeFormat.ISO.DATE);
		System.out.println(dateFormatter.print(new Date(), Locale.CHINA));
		System.out.println(dateFormatter.parse("2020-03-26", Locale.CHINA));
        // 程序打印:
        // 2020-03-26
		// Thu Mar 26 08:00:00 CST 2020
	}
}

AnnotationFormatterFactory——将注解转化成实际的格式化器

public interface AnnotationFormatterFactory<A extends Annotation> {
     
	// 可能被添加注解的字段的类型
	Set<Class<?>> getFieldTypes();
    // 根据注解及字段类型获取一个格式化器
	Printer<?> getPrinter(A annotation, Class<?> fieldType);
    // 根据注解及字段类型获取一个解析器
	Parser<?> getParser(A annotation, Class<?> fieldType);

}

DateTimeFormatAnnotationFormatterFactory实现举例

public class DateTimeFormatAnnotationFormatterFactory  extends EmbeddedValueResolutionSupport
		implements AnnotationFormatterFactory<DateTimeFormat> {
     

	private static final Set<Class<?>> FIELD_TYPES;
	
    // 只有在这些类型下加这个注解才会进行格式化
	static {
     
		Set<Class<?>> fieldTypes = new HashSet<>(4);
		fieldTypes.add(Date.class);
		fieldTypes.add(Calendar.class);
		fieldTypes.add(Long.class);
		FIELD_TYPES = Collections.unmodifiableSet(fieldTypes);
	}


	@Override
	public Set<Class<?>> getFieldTypes() {
     
		return FIELD_TYPES;
	}

	@Override
	public Printer<?> getPrinter(DateTimeFormat annotation, Class<?> fieldType) {
     
		return getFormatter(annotation, fieldType);
	}

	@Override
	public Parser<?> getParser(DateTimeFormat annotation, Class<?> fieldType) {
     
		return getFormatter(annotation, fieldType);
	}
	
	protected Formatter<Date> getFormatter(DateTimeFormat annotation, Class<?> fieldType) {
     			// 通过这个DateFormatter来完成格式化
		DateFormatter formatter = new DateFormatter();
		String style = resolveEmbeddedValue(annotation.style());
		if (StringUtils.hasLength(style)) {
     
			formatter.setStylePattern(style);
		}
		formatter.setIso(annotation.iso());
		String pattern = resolveEmbeddedValue(annotation.pattern());
		if (StringUtils.hasLength(pattern)) {
     
			formatter.setPattern(pattern);
		}
		return formatter;
	}

}

数据格式化——父类链条

格式化管理者—FormatterRegistry
【管理型框架】SpringIOC——数据处理篇(PropertyEditor/ConversionService/TypeConverter/BeanWrapperImpl/Formatting)_第14张图片

// 继承了ConverterRegistry,所以它同时还是一个Converter注册器
public interface FormatterRegistry extends ConverterRegistry {
     
	
    // 一系列添加格式化器的方法
    void addFormatterForFieldType(Class<?> fieldType, Printer<?> printer, Parser<?> parser);
    void addFormatterForFieldType(Class<?> fieldType, Formatter<?> formatter);
    void addFormatterForFieldType(Formatter<?> formatter);
    void addFormatterForAnnotation(AnnotationFormatterFactory<?, ?> factory);
}

【管理型框架】SpringIOC——数据处理篇(PropertyEditor/ConversionService/TypeConverter/BeanWrapperImpl/Formatting)_第15张图片

参考链接:https://blog.csdn.net/qq_41907991/article/details/105237926

数据转化时机(5)——MVC的应用

SpringMVC的RequestParam解析會用到格式化转化器,如果是消息body只会走序列化转化器

public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver{
     
	public void contributeMethodArgument(MethodParameter parameter, @Nullable Object value,
			UriComponentsBuilder builder, Map<String, Object> uriVariables, ConversionService conversionService) {
     

		Class<?> paramType = parameter.getNestedParameterType();
		if (Map.class.isAssignableFrom(paramType) || MultipartFile.class == paramType || Part.class == paramType) {
     
			return;
		}

		RequestParam requestParam = parameter.getParameterAnnotation(RequestParam.class);
		String name = (requestParam != null && StringUtils.hasLength(requestParam.name()) ?
				requestParam.name() : parameter.getParameterName());
      
       /*
          是null不转化
        */
		if (value == null) {
     
			if (requestParam != null &&
					(!requestParam.required() || !requestParam.defaultValue().equals(ValueConstants.DEFAULT_NONE))) {
     
				return;
			}
			builder.queryParam(name);
		}
		/*
          是集合类型则遍历调用convert
        */
		else if (value instanceof Collection) {
     
			for (Object element : (Collection<?>) value) {
     
				element = formatUriValue(conversionService, TypeDescriptor.nested(parameter, 1), element);
				builder.queryParam(name, element);
			}
		}
		/*
          单个对象调用convert
        */
		else {
     
			builder.queryParam(name, formatUriValue(conversionService, new TypeDescriptor(parameter), value));
		}
	}
	/*
	 调用convert实现转化
	 */
   protected String formatUriValue(
			@Nullable ConversionService cs, @Nullable TypeDescriptor sourceType, @Nullable Object value) {
     

		if (value == null) {
     
			return null;
		}
		else if (value instanceof String) {
     
			return (String) value;
		}
		else if (cs != null) {
     
			return (String) cs.convert(value, sourceType, STRING_TYPE_DESCRIPTOR);
		}
		else {
     
			return value.toString();
		}
	}

}

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