• Spring Type Conversion(Spring类型转换源码探究)


    1:概述

    类型转换系统负责Spring框架中对象类型转换和格式化工作。

    ConversionService默认实现UML图如下所示:

    GenericConversionService(通用类型转换服务),是整个类型转换系统的完整实现。作为容器,

    管理转换器,同时调用这些转换器进行类型转换,是一个空的容器,内部没有任何转换器。是线程安全。

    2:GenericConversionService(通用类型转换服务)学习

    (1):转换器缓存设计

    //自定义Map Key实现
        private final Map<ConverterCacheKey, GenericConverter> converterCache = new ConcurrentReferenceHashMap<>(64);
    ​
        /**
         * Key for use with the converter cache.
         */
        private static final class ConverterCacheKey implements Comparable<ConverterCacheKey> {
    ​
            private final TypeDescriptor sourceType;
    ​
            private final TypeDescriptor targetType;
    ​
            public ConverterCacheKey(TypeDescriptor sourceType, TypeDescriptor targetType) {
                this.sourceType = sourceType;
                this.targetType = targetType;
            }
    ​
            @Override
            public boolean equals(Object other) {
                if (this == other) {
                    return true;
                }
                if (!(other instanceof ConverterCacheKey)) {
                    return false;
                }
                ConverterCacheKey otherKey = (ConverterCacheKey) other;
                return (this.sourceType.equals(otherKey.sourceType)) &&
                        this.targetType.equals(otherKey.targetType);
            }
    ​
            @Override
            public int hashCode() {
                return (this.sourceType.hashCode() * 29 + this.targetType.hashCode());
            }
    ​
            @Override
            public String toString() {
                return ("ConverterCacheKey [sourceType = " + this.sourceType +
                        ", targetType = " + this.targetType + "]");
            }
    ​
            @Override
            public int compareTo(ConverterCacheKey other) {
                int result = this.sourceType.getResolvableType().toString().compareTo(
                        other.sourceType.getResolvableType().toString());
                if (result == 0) {
                    result = this.targetType.getResolvableType().toString().compareTo(
                            other.targetType.getResolvableType().toString());
                }
                return result;
            }
        }

    (2):转换器类型适配器设计(适配器模式)

        /**
         * Adapts a {@link Converter} to a {@link GenericConverter}.
         */
        @SuppressWarnings("unchecked")
        private final class ConverterAdapter implements ConditionalGenericConverter {
    
            private final Converter<Object, Object> converter;
    
            private final ConvertiblePair typeInfo;
    
            private final ResolvableType targetType;
    
            public ConverterAdapter(Converter<?, ?> converter, ResolvableType sourceType, ResolvableType targetType) {
                this.converter = (Converter<Object, Object>) converter;
                this.typeInfo = new ConvertiblePair(sourceType.resolve(Object.class), targetType.resolve(Object.class));
                this.targetType = targetType;
            }
    
            @Override
            public Set<ConvertiblePair> getConvertibleTypes() {
                return Collections.singleton(this.typeInfo);
            }
    
            @Override
            public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
                // Check raw type first...
                if (this.typeInfo.getTargetType() != targetType.getObjectType()) {
                    return false;
                }
                // Full check for complex generic type match required?
                ResolvableType rt = targetType.getResolvableType();
                if (!(rt.getType() instanceof Class) && !rt.isAssignableFrom(this.targetType) &&
                        !this.targetType.hasUnresolvableGenerics()) {
                    return false;
                }
                return !(this.converter instanceof ConditionalConverter) ||
                        ((ConditionalConverter) this.converter).matches(sourceType, targetType);
            }
    
            @Override
            @Nullable
            public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
                if (source == null) {
                    return convertNullSource(sourceType, targetType);
                }
                return this.converter.convert(source);
            }
    
            @Override
            public String toString() {
                return (this.typeInfo + " : " + this.converter);
            }
        }
    
    
        private final class ConverterFactoryAdapter implements ConditionalGenericConverter {
    
            private final ConverterFactory<Object, Object> converterFactory;
    
            private final ConvertiblePair typeInfo;
    
            public ConverterFactoryAdapter(ConverterFactory<?, ?> converterFactory, ConvertiblePair typeInfo) {
                this.converterFactory = (ConverterFactory<Object, Object>) converterFactory;
                this.typeInfo = typeInfo;
            }
    
            @Override
            public Set<ConvertiblePair> getConvertibleTypes() {
                return Collections.singleton(this.typeInfo);
            }
    
            @Override
            public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
                boolean matches = true;
                if (this.converterFactory instanceof ConditionalConverter) {
                    matches = ((ConditionalConverter) this.converterFactory).matches(sourceType, targetType);
                }
                if (matches) {
                    Converter<?, ?> converter = this.converterFactory.getConverter(targetType.getType());
                    if (converter instanceof ConditionalConverter) {
                        matches = ((ConditionalConverter) converter).matches(sourceType, targetType);
                    }
                }
                return matches;
            }
    
            @Override
            @Nullable
            public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
                if (source == null) {
                    return convertNullSource(sourceType, targetType);
                }
                return this.converterFactory.getConverter(targetType.getObjectType()).convert(source);
            }
    
            @Override
            public String toString() {
                return (this.typeInfo + " : " + this.converterFactory);
            }
        }

    (3):转换器存储设计

    
    
     private final Converters converters = new Converters();
        
        /**
         * Manages all converters registered with the service.
         */
        private static class Converters {
    ​
            private final Set<GenericConverter> globalConverters = new LinkedHashSet<>();
    ​
            private final Map<ConvertiblePair, ConvertersForPair> converters = new LinkedHashMap<>(36);
        }

    (4):没有操作和没有匹配类型设计

    
    
    /**
         * General NO-OP converter used when conversion is not required.
         */
        private static final GenericConverter NO_OP_CONVERTER = new NoOpConverter("NO_OP");
    ​
        /**
         * Used as a cache entry when no converter is available.
         * This converter is never returned.
         */
        private static final GenericConverter NO_MATCH = new NoOpConverter("NO_MATCH");
    ​
    ​
    ​
            /**
         * Internal converter that performs no operation.
         */
        private static class NoOpConverter implements GenericConverter {
    ​
            private final String name;
    ​
            public NoOpConverter(String name) {
                this.name = name;
            }
    ​
            @Override
            public Set<ConvertiblePair> getConvertibleTypes() {
                return null;
            }
    ​
            @Override
            @Nullable
            public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
                return source;
            }
    ​
            @Override
            public String toString() {
                return this.name;
            }
        }

    总结

    • 适配器合理设计

    • 缓存合理设计

    • 存储合理设计

    • 不匹配和不操作合理设计

    • 读操作设计成一个接口(参照ConversionService)

    • 注册操作设计成一个接口(参照ConverterRegistry)

    • 写操作设计成一个接口(参照ConfigurableConversionService)

    (3):DefaultConversionService源码学习

    默认的类型转换系统,继承了GenericConversionService类。在构造方法调用添加默认的转换器。

    public class DefaultConversionService extends GenericConversionService {
    ​
        @Nullable
        private static volatile DefaultConversionService sharedInstance;
    ​
    ​
        /**
         * Create a new {@code DefaultConversionService} with the set of
         * {@linkplain DefaultConversionService#addDefaultConverters(ConverterRegistry) default converters}.
         */
        public DefaultConversionService() {
            addDefaultConverters(this);
        }
    ​
    ​
        /**
         * Return a shared default {@code ConversionService} instance,
         * lazily building it once needed.
         * <p><b>NOTE:</b> We highly recommend constructing individual
         * {@code ConversionService} instances for customization purposes.
         * This accessor is only meant as a fallback for code paths which
         * need simple type coercion but cannot access a longer-lived
         * {@code ConversionService} instance any other way.
         * @return the shared {@code ConversionService} instance (never {@code null})
         * @since 4.3.5
         */
        public static ConversionService getSharedInstance() {
            DefaultConversionService cs = sharedInstance;
            if (cs == null) {
                synchronized (DefaultConversionService.class) {
                    cs = sharedInstance;
                    if (cs == null) {
                        cs = new DefaultConversionService();
                        sharedInstance = cs;
                    }
                }
            }
            return cs;
        }
    }
    ​
    总结
    
    单例模式之双重检锁模式正确运用
    
    (4):ConversionServiceFactoryBean(类型转换器注册工厂Bean)
    
    /**
     * A factory providing convenient access to a ConversionService configured with
     * converters appropriate for most environments. Set the
     * {@link #setConverters "converters"} property to supplement the default converters.
     *
     * <p>This implementation creates a {@link DefaultConversionService}.
     * Subclasses may override {@link #createConversionService()} in order to return
     * a {@link GenericConversionService} instance of their choosing.
     *
     * <p>Like all {@code FactoryBean} implementations, this class is suitable for
     * use when configuring a Spring application context using Spring {@code <beans>}
     * XML. When configuring the container with
     * {@link org.springframework.context.annotation.Configuration @Configuration}
     * classes, simply instantiate, configure and return the appropriate
     * {@code ConversionService} object from a {@link
     * org.springframework.context.annotation.Bean @Bean} method.
     * @since 3.0
     */
    public class ConversionServiceFactoryBean implements FactoryBean<ConversionService>, InitializingBean {
    ​
        @Nullable
        private Set<?> converters;
    ​
        @Nullable
        private GenericConversionService conversionService;
    ​
    ​
        /**
         * Configure the set of custom converter objects that should be added:
         * implementing {@link org.springframework.core.convert.converter.Converter},
         * {@link org.springframework.core.convert.converter.ConverterFactory},
         * or {@link org.springframework.core.convert.converter.GenericConverter}.
         */
        public void setConverters(Set<?> converters) {
            this.converters = converters;
        }
    ​
        @Override
        public void afterPropertiesSet() {
            this.conversionService = createConversionService();
            ConversionServiceFactory.registerConverters(this.converters, this.conversionService);
        }
    ​
        /**
         * Create the ConversionService instance returned by this factory bean.
         * <p>Creates a simple {@link GenericConversionService} instance by default.
         * Subclasses may override to customize the ConversionService instance that
         * gets created.
         */
        protected GenericConversionService createConversionService() {
            return new DefaultConversionService();
        }
    ​
    ​
        // implementing FactoryBean
    ​
        @Override
        @Nullable
        public ConversionService getObject() {
            return this.conversionService;
        }
    ​
        @Override
        public Class<? extends ConversionService> getObjectType() {
            return GenericConversionService.class;
        }
    ​
        @Override
        public boolean isSingleton() {
            return true;
        }
    ​
    }
    ​
    ​
    /**
     * A factory for common {@link org.springframework.core.convert.ConversionService}
     * configurations.
     * @since 3.0
     */
    public abstract class ConversionServiceFactory {
    ​
        /**
         * Register the given Converter objects with the given target ConverterRegistry.
         * @param converters the converter objects: implementing {@link Converter},
         * {@link ConverterFactory}, or {@link GenericConverter}
         * @param registry the target registry
         */
        public static void registerConverters(@Nullable Set<?> converters, ConverterRegistry registry) {
            if (converters != null) {
                for (Object converter : converters) {
                    if (converter instanceof GenericConverter) {
                        registry.addConverter((GenericConverter) converter);
                    }
                    else if (converter instanceof Converter<?, ?>) {
                        registry.addConverter((Converter<?, ?>) converter);
                    }
                    else if (converter instanceof ConverterFactory<?, ?>) {
                        registry.addConverterFactory((ConverterFactory<?, ?>) converter);
                    }
                    else {
                        throw new IllegalArgumentException("Each converter object must implement one of the " +
                                "Converter, ConverterFactory, or GenericConverter interfaces");
                    }
                }
            }
        }
    ​
    }

    总结

    • 简单工厂模式运用

    • FactoryBean使用

    (5):格式化Formatter体系

    总结

    • 往Spring类型转换系统靠.

    (6):DefaultConversionService可支持转换的列表

    格式:sourceType-targetType

    //简单类型

    Number-->Number

    String-->Number Number-->String

    String-->Character Character-->String

    Number-->Character Character-->Number

    String-->Boolean Boolean-->String

    String-->Enum Enum-->String

    Integer-->Enum Enum-->Integer

    String-->Locale Locale-->String

    String-->Charset Charset->String

    String-->Currency(货币) Currency-->String

    String-->Properties Properties-->String

    String-->UUID UUID-->String

    //集合类型和数组类型

    Object[]-->Collection Collection-->Object[]

    Object[]-->Object[]

    Collection-->Collection

    Map-->Map

    Object[]-->String String-->Object[]

    Object[]-->Object Object-->Object[]

    Collection-->String String-->Collection

    Collection-->Object Object-->Collection

    Stream-->Collection Collection-->Stream

    Stream-->Object[] Object[]-->Stream

    //其他类型

    ByteBuffer-->Object Object-->ByteBuffer

    ByteBuffer-->byte[] byte[]-->ByteBuffer

    String-->TimeZone

    ZoneId-->TimeZone

    ZonedDateTime-->Calendar

    Object-->Object

    Object-->String

    Object-->Optional

    Collection-->Optional

    Object[]-->Optional

  • 相关阅读:
    [tip]build x86+x64 parrelly for your VS solution
    float double的内存表示及比较大小的方法
    [Problem 13]欧拉
    Interface Project
    [复习]内存对齐
    [tip]VS online Gallery in Extention Manager
    [Problem 14]欧拉
    “火柴棍式”程序员面试题打破惯性思维
    [复习]时间复杂度及计算
    ModuleCatalog配置文件
  • 原文地址:https://www.cnblogs.com/liuenyuan1996/p/11071845.html
Copyright © 2020-2023  润新知