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

1:概述

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

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

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

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

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 Type Conversion(Spring类型转换源码探究)

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

总结

  • 往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

 

上一篇:字节跳动CocosCreator面试记录


下一篇:WPF的Style的TargetType不同写法的异同