spring学习(七)类型转换类ConversionService

来源:互联网 发布:防排烟计算软件 编辑:程序博客网 时间:2024/05/16 08:03

spring可以对不同Class类型进行相应的转换。比如String转成Boolean. Boolean转成string类.以下是个简单的例子

@Testpublic void testConverter() {DefaultConversionService serivce = new DefaultConversionService();boolean actual = serivce.canConvert(String.class, Boolean.class);Assert.assertEquals(true, actual);Object acc = serivce.convert("true", Boolean.class);Assert.assertEquals(true, ((Boolean)acc).booleanValue());}


spring类型转换涉及到的类图如下


1、spring是通过ConversionService进行类型转换,通过ConverterRegistry进行转换器注册

其中ConversionService中的方法canConverter判断是否可以转失,convert调用相应的转换器进行类型转换操作

ConverterRegistry中的方法add(Converter)是注册一个转换器

2、对于ConversionService和ConverterRegistry的主要实现类是GenericConversionService。GenericConversionService维护了一个内部类的对象Converters.

当注册一个converter时。会生成一个GenericeConverter的适配类ConverterAdapter,并注册到内部类Converters中

public void addConverter(Converter<?, ?> converter) {GenericConverter.ConvertiblePair typeInfo = getRequiredTypeInfo(converter, Converter.class);Assert.notNull(typeInfo, "Unable to the determine sourceType <S> and targetType " +"<T> which your Converter<S, T> converts between; declare these generic types.");addConverter(new ConverterAdapter(typeInfo, converter));}public void addConverter(Class<?> sourceType, Class<?> targetType, Converter<?, ?> converter) {GenericConverter.ConvertiblePair typeInfo = new GenericConverter.ConvertiblePair(sourceType, targetType);addConverter(new ConverterAdapter(typeInfo, converter));}public void addConverter(GenericConverter converter) {this.converters.add(converter);invalidateCache();}

内部类Converters中维护了一个Map用于存放先前注册的所有Converter

private static class Converters {private final Set<GenericConverter> globalConverters =new LinkedHashSet<GenericConverter>();private final Map<ConvertiblePair, ConvertersForPair> converters =new LinkedHashMap<ConvertiblePair, ConvertersForPair>(36);public void add(GenericConverter converter) {Set<ConvertiblePair> convertibleTypes = converter.getConvertibleTypes();if (convertibleTypes == null) {Assert.state(converter instanceof ConditionalConverter,"Only conditional converters may return null convertible types");globalConverters.add(converter);}else {for (ConvertiblePair convertiblePair : convertibleTypes) {ConvertersForPair convertersForPair = getMatchableConverters(convertiblePair);convertersForPair.add(converter);}}}
3、当调用canConvert时,会调用内部类的方法find方法查找转换的类型sourceType和targetType是否进行了注册

protected GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {ConverterCacheKey key = new ConverterCacheKey(sourceType, targetType);GenericConverter converter = this.converterCache.get(key);if (converter != null) {return (converter != NO_MATCH ? converter : null);}converter = this.converters.find(sourceType, targetType);if (converter == null) {converter = getDefaultConverter(sourceType, targetType);}if (converter != null) {this.converterCache.put(key, converter);return converter;}this.converterCache.put(key, NO_MATCH);return null;}
其中内部类Converters的find方法根据sourceType和targetType去查询Converters中维护的Map中是否包括支持的注册类型,如果存在返回GenericConverter的适配类ConverterAdapter,如果没有存在返回null

public GenericConverter find(TypeDescriptor sourceType, TypeDescriptor targetType) {// Search the full type hierarchyList<Class<?>> sourceCandidates = getClassHierarchy(sourceType.getType());List<Class<?>> targetCandidates = getClassHierarchy(targetType.getType());for (Class<?> sourceCandidate : sourceCandidates) {for (Class<?> targetCandidate : targetCandidates) {ConvertiblePair convertiblePair = new ConvertiblePair(sourceCandidate, targetCandidate);GenericConverter converter = getRegisteredConverter(sourceType, targetType, convertiblePair);if(converter != null) {return converter;}}}return null;}private GenericConverter getRegisteredConverter(TypeDescriptor sourceType,TypeDescriptor targetType, ConvertiblePair convertiblePair) {// Check specifically registered convertersConvertersForPair convertersForPair = converters.get(convertiblePair);GenericConverter converter = convertersForPair == null ? null: convertersForPair.getConverter(sourceType, targetType);if (converter != null) {return converter;}// Check ConditionalGenericConverter that match all typesfor (GenericConverter globalConverter : this.globalConverters) {if (((ConditionalConverter)globalConverter).matches(sourceType, targetType)) {return globalConverter;}}return null;}

4、当查找到注册的类型转换器时GenericConverter时。会调用ConverterAdapter中的convert方法。ConverterAdapter中的convert方法会调用相当维护的converter并转换

public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {if (source == null) {return convertNullSource(sourceType, targetType);}return this.converter.convert(source);}

5、spring的注册类型转换器时,是通过GenericConversionService的子类DefaultConversionService实现的

private static void addScalarConverters(ConverterRegistry converterRegistry) {ConversionService conversionService = (ConversionService) converterRegistry;converterRegistry.addConverter(new StringToBooleanConverter());converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter());converterRegistry.addConverterFactory(new StringToNumberConverterFactory());converterRegistry.addConverter(Number.class, String.class, new ObjectToStringConverter());converterRegistry.addConverterFactory(new NumberToNumberConverterFactory());converterRegistry.addConverter(new StringToCharacterConverter());converterRegistry.addConverter(Character.class, String.class, new ObjectToStringConverter());converterRegistry.addConverter(new NumberToCharacterConverter());converterRegistry.addConverterFactory(new CharacterToNumberFactory());converterRegistry.addConverterFactory(new StringToEnumConverterFactory());converterRegistry.addConverter(Enum.class, String.class, new EnumToStringConverter(conversionService));converterRegistry.addConverter(new StringToLocaleConverter());converterRegistry.addConverter(Locale.class, String.class, new ObjectToStringConverter());converterRegistry.addConverter(new PropertiesToStringConverter());converterRegistry.addConverter(new StringToPropertiesConverter());converterRegistry.addConverter(new StringToUUIDConverter());converterRegistry.addConverter(UUID.class, String.class, new ObjectToStringConverter());}


1 0
原创粉丝点击