概述
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 添加转换器所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复