Spring源码学习笔记

前言

想找一个简化版本的 spring 接口设计用来学习(包含关键设计, 如拦截器链、配置、前后置处理器等), 奈何实例不允许, 所以记下知识碎片先行学习。

类型转换

spring在org.springframework.core.convert.converter包中定义了三种类型转换器接口:Converter、ConverterFactory、GenericConverter。

一、Converter

1
2
3
4
5
@FunctionalInterface
public interface Converter<S, T> {
@Nullable
T convert(S source);
}

Converter能将S类型的对象转换为T类型的对象,比如将String类型的对象转换为Integer类型的对象的实现类:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class StringToIntegerConverter implements Converter<String, Integer> {

@Override
public Integer convert(String source) {
return Integer.valueOf(source);
}

public static void main(String[] args) {
StringToIntegerConverter converter = new StringToIntegerConverter();
Integer convert = converter.convert("123");
System.out.println(convert);
}
}

二、ConverterFactory

1
2
3
public interface ConverterFactory<S, R> {
<T extends R> Converter<S, T> getConverter(Class<T> targetType);
}

Converter<S,T>接口适合一对一的类型转换,如果要将String类型转换为Ineger/Long/Float/Double/Decimal等类型,就要实现一系列的StringToInteger/StringToLongConverter/StringToFloatConverter转换器,非常不优雅。

ConverterFactory接口则适合一对多的类型转换,可以将一种类型转换为另一种类型及其子类。比如将String类型转换为Ineger/Long/Float/Double/Decimal等Number类型时,只需定义一个ConverterFactory转换器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class StringToNumberConverterFactory implements ConverterFactory<String, Number> {

@Override
public <T extends Number> Converter<String, T> getConverter(Class<T> targetType) {
return new StringToNumber<>(targetType);
}

private static final class StringToNumber<T extends Number> implements Converter<String, T> {

private final Class<T> targetType;

public StringToNumber(Class<T> targetType) {
this.targetType = targetType;
}

@Override
public T convert(String source) {
if (source.length() == 0) {
return null;
}

if (targetType.equals(Integer.class)) {
return (T) Integer.valueOf(source);
} else if (targetType.equals(Long.class)) {
return (T) Long.valueOf(source);
}

else {
throw new IllegalArgumentException(
"Cannot convert String [" + source + "] to target class [" + targetType.getName() + "]");
}
}
}

public static void main(String[] args) {
StringToNumberConverterFactory stringToNumberConverterFactory = new StringToNumberConverterFactory();
Converter<String, Integer> converter = stringToNumberConverterFactory.getConverter(Integer.class);
Integer convert = converter.convert("123");
System.out.println(convert);
}
}

三、GenericConverter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class StringToBooleanConverter implements GenericConverter {
@Override
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(String.class, Boolean.class));
}

@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
return Boolean.valueOf((String) source);
}

public static void main(String[] args) {
Object aTrue = new StringToBooleanConverter().convert("true", TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Boolean.class));
System.out.println(aTrue);
}
}