我是靠谱客的博主 无奈金针菇,最近开发中收集的这篇文章主要介绍SpringBoot转换服务ApplicationConversionService1. 源码分析2.GenericConversionService 实现方式3. ApplicationConversionService 添加转换器,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1. 源码分析

Intellij idea Diagrams

 具体分析如下:

2.GenericConversionService 实现方式

最左侧通用转换服务(GenericConversionService)使用案例:

//  以下为测试类

GenericConversionService service = new GenericConversionService();

// 将 String 类型的时间转换为 util.Date
service.addConverter(new Converter<String, Date>() {
    @Override
    public Date convert(String source) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return format.parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
});
// 将 Integer 转换为 String,Double,Boolean
service.addConverter(new GenericConverter() {
    @Override
    public Set<ConvertiblePair> getConvertibleTypes() {
        return new HashSet<ConvertiblePair>() {{
            add(new ConvertiblePair(Integer.class, String.class));
            add(new ConvertiblePair(Integer.class, Double.class));
            add(new ConvertiblePair(Integer.class, Boolean.class));
        }};
    }

    @Override
    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
        Class<?> type = targetType.getType();
        if (String.class.equals(type)) {
            return source.toString();
        } else if (Double.class.equals(type)) {
            return Double.valueOf(source.toString());
        } else if (Boolean.class.equals(type)) {
            return Boolean.valueOf(source.toString());
        }
        return null;
    }
});
// String 转 Boolean
service.addConverter(String.class, Boolean.class, new Converter<String, Boolean>() {
    @Override
    public Boolean convert(String source) {
        return Boolean.parseBoolean(source);
    }
});
// String 转 Integer,Long
service.addConverterFactory(new ConverterFactory<String, Number>() {
    @Override
    public <T extends Number> Converter<String, T> getConverter(Class<T> targetType) {
        if(targetType.getTypeName().equals(Integer.class.getTypeName())) {
            return new Converter<String, T>() {
                @Override
                public T convert(String source) {
                    return (T) NumberUtils.parseNumber(source, Integer.class);
                }
            };
        } else if(targetType.getTypeName().equals(Long.class.getTypeName())) {
            return new Converter<String, T>() {
                @Override
                public T convert(String source) {
                    return (T) NumberUtils.parseNumber(source, Long.class);
                }
            };
        }
        return null;
    }
});

Boolean checkTimeToDate = service.canConvert(Map.class, List.class);
System.out.println("Map能否转换为List:" + checkTimeToDate);
Date targetDate = service.convert("2021-12-20 13:01:01", Date.class);
System.out.println(targetDate);
String targetString = service.convert(1, String.class);
System.out.println(targetString);
Double targetDouble = service.convert(1, Double.class);
System.out.println(targetDouble);
Boolean targetBoolean = service.convert(1, Boolean.class);
System.out.println(targetBoolean);
Boolean stringToBoolean = service.convert("true", Boolean.class);
System.out.println(stringToBoolean);
Integer stringToInteger = service.convert("200", Integer.class);
System.out.println(stringToInteger);
Long stringToLong = service.convert("300", Long.class);
System.out.println(stringToLong);

使用一个 ConcurrentReferenceHashMap Spring封装的线程安全HashMap,作为缓存,可能会被垃圾回收,只做临时存储,默认Map长度 64。

使用 Converters 存储实际转换器。

GenericConversionService.java 第78行

private final Converters converters = new Converters();

private final Map<ConverterCacheKey, GenericConverter> converterCache = new ConcurrentReferenceHashMap<>(64);

必知:GenericConverter 通用转换器,定义了 可转换类型 和 转换方法。

Converters具体存储数据格式如下:

GenericConversionService.java 第503行两个集合

Set: [
    GenericConverter: {
        ConvertiblePair: {
            sourceType: '原类型',
            targetType: '目标类型',
            equals: '重写equals方法'
        },
        Converter<Object, Object> : '转换接口'
    }
]

Map {
    ConvertiblePair: ConvertersForPair: {
        converters: [ GenericConverter, GenericConverter, GenericConverter ]
    }
}

上图 Set 集合似乎没啥用,从没用到过,不做解释。

核心使用 线程安全HashMap ConcurrentHashMap 去做数据存储和查询。

通过 ConvertiblePair 重写HasCode,调用 Map.get 得到 ConvertersForPair。

ConvertersForPair.converters 是一个 ConcurrentLinkedDeque 线程安全队列,每次向前插数据。

循环从索引0开始++,所以后加入的则会被先匹配。

3. ApplicationConversionService 添加转换器

ApplicationConversionService 负责定义转换器,其他实现类在其上加入特有转换器。

ApplicationConversionService.java 第96行

public static void configure(FormatterRegistry registry) {
	DefaultConversionService.addDefaultConverters(registry);
	DefaultFormattingConversionService.addDefaultFormatters(registry);
	addApplicationFormatters(registry);
	addApplicationConverters(registry);
}

最后

以上就是无奈金针菇为你收集整理的SpringBoot转换服务ApplicationConversionService1. 源码分析2.GenericConversionService 实现方式3. ApplicationConversionService 添加转换器的全部内容,希望文章能够帮你解决SpringBoot转换服务ApplicationConversionService1. 源码分析2.GenericConversionService 实现方式3. ApplicationConversionService 添加转换器所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(33)

评论列表共有 0 条评论

立即
投稿
返回
顶部