源码分析-Mybatis源码阅读-类型处理器

源码解析-Mybatis
01 源码分析-Mybatis源码阅读准备
02 源码分析-Mybatis源码阅读-会话层
03 源码分析-Mybatis源码阅读-执行器
04 源码分析-Mybatis源码阅读-Statement语句处理器
05 源码分析-Mybatis源码阅读-参数处理器
06 源码分析-Mybatis源码阅读-结果集处理器
07 源码分析-Mybatis源码阅读-主键生成器
08 源码分析-Mybatis源码阅读-懒加载机制
09 源码分析-Mybatis源码阅读-游标
10 源码分析-Mybatis源码阅读-类型处理器
11 源码分析-Mybatis源码阅读-缓存
12 源码分析-Mybatis源码阅读-Mapper代理

一 类型处理器说明

类型处理器代码主要在org.apache.ibatis.type包下,类型处理器类说明如下:

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
.
└── org
└── apache
└── ibatis
└── type
   ├── Alias.java 指定别名的注解
   ├── ArrayTypeHandler.java 数组类型处理器实现
   ├── BaseTypeHandler.java 抽象的基础类型处理器
   ├── BigDecimalTypeHandler.java BigDecimal类型处理器实现
   ├── BigIntegerTypeHandler.java BigInteger类型处理器实现
   ├── BlobByteObjectArrayTypeHandler.java BlobByteObjectArray类型处理器
   ├── BlobInputStreamTypeHandler.java BlobInputStream类型处理器
   ├── BlobTypeHandler.java Blob类型处理器
   ├── BooleanTypeHandler.java Boolean类型处理器
   ├── ByteArrayTypeHandler.java ByteArray类型处理器
   ├── ByteArrayUtils.java 字节数组工具类
   ├── ByteObjectArrayTypeHandler.java ByteObjectArray类型处理器
   ├── ByteTypeHandler.java Byte类型处理器
   ├── CharacterTypeHandler.java Character类型处理器
   ├── ClobReaderTypeHandler.java ClobReader类型处理器
   ├── ClobTypeHandler.java Clob类型处理器
   ├── DateOnlyTypeHandler.java DateOnly类型处理器
   ├── DateTypeHandler.java Date类型处理器
   ├── DoubleTypeHandler.java Double类型处理器
   ├── EnumOrdinalTypeHandler.java 枚举序数类型处理器
   ├── EnumTypeHandler.java 枚举类型处理器
   ├── FloatTypeHandler.java Float类型处理器
   ├── InstantTypeHandler.java Instant类型处理器
   ├── IntegerTypeHandler.java Integer类型处理器
   ├── JapaneseDateTypeHandler.java JapaneseDate类型处理器
   ├── JdbcType.java jdbc类型枚举
   ├── LocalDateTimeTypeHandler.java LocalDateTime类型处理器
   ├── LocalDateTypeHandler.java LocalDate类型处理器
   ├── LocalTimeTypeHandler.java LocalTime类型处理器
   ├── LongTypeHandler.java Long类型处理器
   ├── MappedJdbcTypes.java 指定要映射的 jdbc 类型的注解
   ├── MappedTypes.java 指定要映射的 java 类型的注解
   ├── MonthTypeHandler.java Month类型处理器
   ├── NClobTypeHandler.java NClob类型处理器
   ├── NStringTypeHandler.java NString类型处理器
   ├── ObjectTypeHandler.java 对象类型处理器-当找不到类型处理器是的默认处理器
   ├── OffsetDateTimeTypeHandler.java OffsetDateTime类型处理器
   ├── OffsetTimeTypeHandler.java OffsetTime类型处理器
   ├── ShortTypeHandler.java Short类型处理器
   ├── SimpleTypeRegistry.java 基本数据类型处理器
   ├── SqlDateTypeHandler.java SqlDate类型处理器
   ├── SqlTimeTypeHandler.java SqlTimeT类型处理器
   ├── SqlTimestampTypeHandler.java SqlTimestamp类型处理器
   ├── SqlxmlTypeHandler.java Sqlxml类型处理器
   ├── StringTypeHandler.java String类型处理器
   ├── TimeOnlyTypeHandler.java TimeOnlyT类型处理器
   ├── TypeAliasRegistry.java
   ├── TypeException.java
   ├── TypeHandler.java 类型处理器接口
   ├── TypeHandlerRegistry.java 类型处理器注册器
   ├── TypeReference.java 引用泛型类型
   ├── UnknownTypeHandler.java 未知类型处理器
   ├── YearMonthTypeHandler.java YearMonth类型处理器
   ├── YearTypeHandler.java Year类型处理器
   └── ZonedDateTimeTypeHandler.java ZonedDateTime类型处理器

类型处理器UML图如下:

image-20210603195538815

二 类型处理器源码解析

TypeHandler源码解析如下:

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
/**
* 类型处理器
* <p>
* 无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时,
* 都会用类型处理器将获取的值以合适的方式转换成 Java 类型
* </p>
*
* @author Clinton Begin
*/
public interface TypeHandler<T> {

/**
* 把 java 对象设置到 PreparedStatement 的参数中
* @param i 从1开始
*/
void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;

/**
* 从 ResultSet 中取出columnName对应数据,然后转换为 java 对象
* @param columnName Colunm name, when configuration <code>useColumnLabel</code> is <code>false</code>
*/
T getResult(ResultSet rs, String columnName) throws SQLException;

/**
* 用于从 ResultSet 中取出数据转换为 java 对象
*/
T getResult(ResultSet rs, int columnIndex) throws SQLException;

/**
* 用于从 CallableStatement 中取出数据转换为 java 对象
*/
T getResult(CallableStatement cs, int columnIndex) throws SQLException;

}

TypeReference源码解析如下:

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/**
* 引用泛型类型
* References a generic type.
*
* @param <T> the referenced type
* @since 3.1.0
* @author Simone Tripodi
*/
public abstract class TypeReference<T> {

/**
* java原生类型、即T泛型的类型
*/
private final Type rawType;

protected TypeReference() {
rawType = getSuperclassTypeParameter(getClass());
}

/**
* rawType的获取过程。任务类型处理器都需要继承BaseTypeHandle<T>,而BaseTypeHandle<T>继承TypeReference<T>,此处为了获取T的java类型。
* 至于为什么使用这一变量,因为我们自定义类型处理器可以不指定java类型,只指定jdbc类型,这样java类型默认就是T类型。
* @param clazz
* @return
*/
Type getSuperclassTypeParameter(Class<?> clazz) {
// 获取父类,包括T。此处和getSuperClass的区别是,getSuperClass只返回直接父类,并不包括父类带的泛型T
Type genericSuperclass = clazz.getGenericSuperclass();
// 任何类型处理器都有泛型T,一直循环找,如果没找到,直接报错。
if (genericSuperclass instanceof Class) {
// try to climb up the hierarchy until meet something useful
if (TypeReference.class != genericSuperclass) {
return getSuperclassTypeParameter(clazz.getSuperclass());
}

throw new TypeException("'" + getClass() + "' extends TypeReference but misses the type parameter. "
+ "Remove the extension or add a type parameter to it.");
}

// 获取泛型T的java类型
Type rawType = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
// TODO remove this when Reflector is fixed to return Types
if (rawType instanceof ParameterizedType) {
rawType = ((ParameterizedType) rawType).getRawType();
}

return rawType;
}

public final Type getRawType() {
return rawType;
}

@Override
public String toString() {
return rawType.toString();
}

}

BaseTypeHandler源码解析如下:

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/**
* 一个基本的{@link TypeHandler}引用了一个泛型类型
* The base {@link TypeHandler} for references a generic type.
* <p>
* Important: Since 3.5.0, This class never call the {@link ResultSet#wasNull()} and
* {@link CallableStatement#wasNull()} method for handling the SQL {@code NULL} value.
* In other words, {@code null} value handling should be performed on subclass.
*
* 重要提示:从 3.5.0 开始,此类从不调用 {@link ResultSet#wasNull()} 和 {@link CallableStatement#wasNull()} 方法来处理 SQL {@code NULL} 值。
* 换句话说,{@code null} 值处理应该在子类上执行。
* </p>
*
* @author Clinton Begin
* @author Simone Tripodi
* @author Kzuki Shimizu
*/
public abstract class BaseTypeHandler<T> extends TypeReference<T> implements TypeHandler<T> {

/**
* @deprecated Since 3.5.0 - See https://github.com/mybatis/mybatis-3/issues/1203. This field will remove future.
*/
@Deprecated
protected Configuration configuration;

/**
* Sets the configuration.
*
* @param c
* the new configuration
* @deprecated Since 3.5.0 - See https://github.com/mybatis/mybatis-3/issues/1203. This property will remove future.
*/
@Deprecated
public void setConfiguration(Configuration c) {
this.configuration = c;
}

/**
* 把 java 对象设置到 PreparedStatement 的参数中
* <p>
* 解决 {@link @paramter} ,{@link @jdbcType} 的情况。
* </p>
* <ol>
* <li>{@link @jdbcType}为null,抛出 {@link TypeException},也就是说{@link @jdbcType}调用这个方法的时候就已经确定了</li>
* <li>{@link @parameter}为null时,对第{@link @i}个'?'设置null值;否则,
* 调用抽象方法{@link BaseTypeHandler#setNonNullParameter(PreparedStatement, int, Object, JdbcType)}</li>
* </ol>
*/
@Override
public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
if (parameter == null) {
// 一般情况下,jdbcType到这个方法时就已经确定了jdbcType.TYPE_CODE,
if (jdbcType == null) {
throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
}
try {
// 设置null值。
ps.setNull(i, jdbcType.TYPE_CODE);
} catch (SQLException e) {
throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . "
+ "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. "
+ "Cause: " + e, e);
}
} else {
try {
setNonNullParameter(ps, i, parameter, jdbcType);
} catch (Exception e) {
throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . "
+ "Try setting a different JdbcType for this parameter or a different configuration property. "
+ "Cause: " + e, e);
}
}
}

/**
* 用于从 ResultSet 中取出数据转换为 java 对象
* <p>
* 直接调用{@link BaseTypeHandler#getNullableResult(ResultSet, String)}
* </p>
*/
@Override
public T getResult(ResultSet rs, String columnName) throws SQLException {
try {
return getNullableResult(rs, columnName);
} catch (Exception e) {
throw new ResultMapException("Error attempting to get column '" + columnName + "' from result set. Cause: " + e, e);
}
}

/**
* 用于从 ResultSet 中取出数据转换为 java 对象
* <p>
* 直接调用{@link BaseTypeHandler#getNullableResult(ResultSet, String)}
* </p>
*/
@Override
public T getResult(ResultSet rs, int columnIndex) throws SQLException {
try {
return getNullableResult(rs, columnIndex);
} catch (Exception e) {
throw new ResultMapException("Error attempting to get column #" + columnIndex + " from result set. Cause: " + e, e);
}
}

/**
* 用于从 CallableStatement 中取出数据转换为 java 对象
* <p>
* 直接调用{@link BaseTypeHandler#getNullableResult(ResultSet, String)}
* </p>
*/
@Override
public T getResult(CallableStatement cs, int columnIndex) throws SQLException {
try {
return getNullableResult(cs, columnIndex);
} catch (Exception e) {
throw new ResultMapException("Error attempting to get column #" + columnIndex + " from callable statement. Cause: " + e, e);
}
}

/**
* 设置不为空的参数
*/
public abstract void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;

/**
* 获取可空的结果
* Gets the nullable result.
*
* @param rs
* the rs
* @param columnName
* Colunm name, when configuration <code>useColumnLabel</code> is <code>false</code>
* @return the nullable result
* @throws SQLException
* the SQL exception
*/
public abstract T getNullableResult(ResultSet rs, String columnName) throws SQLException;

/**
* 获取可空的结果
*/
public abstract T getNullableResult(ResultSet rs, int columnIndex) throws SQLException;

/**
* 获取可空的结果
*/
public abstract T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException;

}

ObjectTypeHandler源码解析如下:

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
42
/**
* Object 类型处理器
* @author Clinton Begin
*/
public class ObjectTypeHandler extends BaseTypeHandler<Object> {

/**
* 直接调用 {@link PreparedStatement#setObject(int, Object)}
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
throws SQLException {
ps.setObject(i, parameter);
}

/**
* 直接调用 {@link ResultSet#getObject(String)}
*/
@Override
public Object getNullableResult(ResultSet rs, String columnName)
throws SQLException {
return rs.getObject(columnName);
}

/**
* 直接调用 {@link ResultSet#getObject(int)}
*/
@Override
public Object getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
return rs.getObject(columnIndex);
}

/**
* 直接调用 {@link CallableStatement#getObject(int)}
*/
@Override
public Object getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
return cs.getObject(columnIndex);
}
}

UnknownTypeHandler源码解析如下:

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/**
* 未知类型处理器
* <p>在{@link BaseTypeHandler}的抽象方法中根据返回的结果集提供的列去获取对应的TypeHandler时候,
* 在获取不到的情况下,就会使用{@link ObjectTypeHandler}处理</p>
* @author Clinton Begin
*/
public class UnknownTypeHandler extends BaseTypeHandler<Object> {

private static final ObjectTypeHandler OBJECT_TYPE_HANDLER = new ObjectTypeHandler();
// TODO Rename to 'configuration' after removing the 'configuration' property(deprecated property) on parent class
private final Configuration config;
private final Supplier<TypeHandlerRegistry> typeHandlerRegistrySupplier;

/**
* The constructor that pass a MyBatis configuration.
*
* @param configuration a MyBatis configuration
* @since 3.5.4
*/
public UnknownTypeHandler(Configuration configuration) {
this.config = configuration;
this.typeHandlerRegistrySupplier = configuration::getTypeHandlerRegistry;
}

/**
* The constructor that pass the type handler registry.
*
* @param typeHandlerRegistry a type handler registry
* @deprecated Since 3.5.4, please use the {@link #UnknownTypeHandler(Configuration)}.
*/
@Deprecated
public UnknownTypeHandler(TypeHandlerRegistry typeHandlerRegistry) {
this.config = new Configuration();
this.typeHandlerRegistrySupplier = () -> typeHandlerRegistry;
}

@Override
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
throws SQLException {
TypeHandler handler = resolveTypeHandler(parameter, jdbcType);
handler.setParameter(ps, i, parameter, jdbcType);
}

@Override
public Object getNullableResult(ResultSet rs, String columnName)
throws SQLException {
TypeHandler<?> handler = resolveTypeHandler(rs, columnName);
return handler.getResult(rs, columnName);
}

@Override
public Object getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
TypeHandler<?> handler = resolveTypeHandler(rs.getMetaData(), columnIndex);
if (handler == null || handler instanceof UnknownTypeHandler) {
handler = OBJECT_TYPE_HANDLER;
}
return handler.getResult(rs, columnIndex);
}

@Override
public Object getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
return cs.getObject(columnIndex);
}

/**
* 解析获取类型处理器
* <p>根据 {@code parameter} 和 {@code jdbcType} 获取typeHandler实例</p>
* @return {@code parameter} 为null 或者
* 获取不了对应{@code parameter} 和 {@code jdbcType} 的typeHanlder实例
* 或者为typeHandler实例都为{@link UnknownTypeHandler}的实例的话,都会返回{@link #OBJECT_TYPE_HANDLER}
*/
private TypeHandler<?> resolveTypeHandler(Object parameter, JdbcType jdbcType) {
TypeHandler<?> handler;
if (parameter == null) {
handler = OBJECT_TYPE_HANDLER;
} else {
handler = typeHandlerRegistrySupplier.get().getTypeHandler(parameter.getClass(), jdbcType);
// check if handler is null (issue #270)
if (handler == null || handler instanceof UnknownTypeHandler) {
handler = OBJECT_TYPE_HANDLER;
}
}
return handler;
}

/**
* 解析获取TypeHandler实例
* <p>
* 通过{@code rs}拿到结果集的描述信息{@link ResultSetMetaData},根据描述信息去拿到列名对应的
* 位置,再调用{@link #resolveTypeHandler(ResultSetMetaData, Integer)}获取对应的TypeHandler实例。
* </p>
* @param rs 结果集
* @param column 列名
* @return {@link TypeHandler} 实例;
* 当 {@code handler} 为null或者 {@code handler} 为 {@link UnknownTypeHandler} 就会返回 {@link #OBJECT_TYPE_HANDLER}
*/
private TypeHandler<?> resolveTypeHandler(ResultSet rs, String column) {
try {
// 将所有列的列名,对应的位置都拿出来放到columnIndexLookup中
Map<String,Integer> columnIndexLookup;
columnIndexLookup = new HashMap<>();
ResultSetMetaData rsmd = rs.getMetaData();
int count = rsmd.getColumnCount();
boolean useColumnLabel = config.isUseColumnLabel();
for (int i = 1; i <= count; i++) {
String name = useColumnLabel ? rsmd.getColumnLabel(i) : rsmd.getColumnName(i);
columnIndexLookup.put(name,i);
}
Integer columnIndex = columnIndexLookup.get(column);
TypeHandler<?> handler = null;
if (columnIndex != null) {
handler = resolveTypeHandler(rsmd, columnIndex);
}
if (handler == null || handler instanceof UnknownTypeHandler) {
handler = OBJECT_TYPE_HANDLER;
}
return handler;
} catch (SQLException e) {
throw new TypeException("Error determining JDBC type for column " + column + ". Cause: " + e, e);
}
}

/**
* 解析获取TypeHandler实例
* @param rsmd 结果集描述信息
* @param columnIndex 指定的列位置
* @return TypeHandler实例
*/
private TypeHandler<?> resolveTypeHandler(ResultSetMetaData rsmd, Integer columnIndex) {
TypeHandler<?> handler = null;
// 从columnIndex中获取jdbcType,不会抛出异常,但是会返回null
JdbcType jdbcType = safeGetJdbcTypeForColumn(rsmd, columnIndex);
// 从columnIndex中获取javaType,不会抛出异常,但是会返回null
Class<?> javaType = safeGetClassForColumn(rsmd, columnIndex);
// 根据现有的条件,尽可能的找到对应的typeHandler实例
if (javaType != null && jdbcType != null) {
handler = typeHandlerRegistrySupplier.get().getTypeHandler(javaType, jdbcType);
} else if (javaType != null) {
handler = typeHandlerRegistrySupplier.get().getTypeHandler(javaType);
} else if (jdbcType != null) {
handler = typeHandlerRegistrySupplier.get().getTypeHandler(jdbcType);
}
return handler;
}

/**
* 安全的从列中拿到jdbcType,这里的安全应该是指捕捉的所有获取过程中抛出的异常。
* @param rsmd 结果集的描述信息
* @param columnIndex 指定的列位置
* @return {@link JdbcType},在获取过程中抛出异常会返回 {@code null}
*/
private JdbcType safeGetJdbcTypeForColumn(ResultSetMetaData rsmd, Integer columnIndex) {
try {
return JdbcType.forCode(rsmd.getColumnType(columnIndex));
} catch (Exception e) {
return null;
}
}

/**
* 安全的从列中拿到javaType,这里的安全应该是指捕捉的所有获取过程中抛出的异常。
* @param rsmd 结果集的描述信息
* @param columnIndex 指定的列位置
* @return {@link Class},在获取过程中抛出异常会返回 {@code null}
*/
private Class<?> safeGetClassForColumn(ResultSetMetaData rsmd, Integer columnIndex) {
try {
return Resources.classForName(rsmd.getColumnClassName(columnIndex));
} catch (Exception e) {
return null;
}
}
}

TypeHandlerRegistry类型处理器注册器的源码解析如下

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
/**
* 类型处理注册器
* @author Clinton Begin
* @author Kazuki Shimizu
*/
public final class TypeHandlerRegistry {

/**
* 枚举类JdbcType作为键,完成数据库类型与类型处理器的对应注册
*/
private final Map<JdbcType, TypeHandler<?>> jdbcTypeHandlerMap = new EnumMap<>(JdbcType.class);

/**
* Java类型作为键,JdbcType与TypeHandler的映射关系作为value,完成Java类型、数据库类型和类型处理器三者的对应注册
*/
private final Map<Type, Map<JdbcType, TypeHandler<?>>> typeHandlerMap = new ConcurrentHashMap<>();

/**
* 对未知类型的注册,如Object
* 其实还是在{@link BaseTypeHandler}的抽象方法中根据返回的结果集提供的列去获取对应的TypeHandler时候,
* 在获取不到的情况下,就会使用{@link ObjectTypeHandler}处理
*/
private final TypeHandler<Object> unknownTypeHandler;

/**
* 保存着所有的类型处理器实例,是以类型处理器的类类型为键值保存的,它可以统筹所有的类型处理器实例
*/
private final Map<Class<?>, TypeHandler<?>> allTypeHandlersMap = new HashMap<>();

/**
* 空TypeHandler集合的标识
*/
private static final Map<JdbcType, TypeHandler<?>> NULL_TYPE_HANDLER_MAP = Collections.emptyMap();

/**
* 默认的枚举类型处理器类
*/
private Class<? extends TypeHandler> defaultEnumTypeHandler = EnumTypeHandler.class;

/**
* The default constructor.
*/
public TypeHandlerRegistry() {
this(new Configuration());
}

/**
* 注册一些基本的,常用的TypeHandler
* The constructor that pass the MyBatis configuration.
*
* @param configuration a MyBatis configuration
* @since 3.5.4
*/
public TypeHandlerRegistry(Configuration configuration) {
this.unknownTypeHandler = new UnknownTypeHandler(configuration);

register(Boolean.class, new BooleanTypeHandler());
register(boolean.class, new BooleanTypeHandler());
register(JdbcType.BOOLEAN, new BooleanTypeHandler());
register(JdbcType.BIT, new BooleanTypeHandler());

register(Byte.class, new ByteTypeHandler());
register(byte.class, new ByteTypeHandler());
register(JdbcType.TINYINT, new ByteTypeHandler());

register(Short.class, new ShortTypeHandler());
register(short.class, new ShortTypeHandler());
register(JdbcType.SMALLINT, new ShortTypeHandler());

register(Integer.class, new IntegerTypeHandler());
register(int.class, new IntegerTypeHandler());
register(JdbcType.INTEGER, new IntegerTypeHandler());

register(Long.class, new LongTypeHandler());
register(long.class, new LongTypeHandler());

register(Float.class, new FloatTypeHandler());
register(float.class, new FloatTypeHandler());
register(JdbcType.FLOAT, new FloatTypeHandler());

register(Double.class, new DoubleTypeHandler());
register(double.class, new DoubleTypeHandler());
register(JdbcType.DOUBLE, new DoubleTypeHandler());

register(Reader.class, new ClobReaderTypeHandler());
register(String.class, new StringTypeHandler());
register(String.class, JdbcType.CHAR, new StringTypeHandler());
register(String.class, JdbcType.CLOB, new ClobTypeHandler());
register(String.class, JdbcType.VARCHAR, new StringTypeHandler());
register(String.class, JdbcType.LONGVARCHAR, new StringTypeHandler());
register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler());
register(String.class, JdbcType.NCHAR, new NStringTypeHandler());
register(String.class, JdbcType.NCLOB, new NClobTypeHandler());
register(JdbcType.CHAR, new StringTypeHandler());
register(JdbcType.VARCHAR, new StringTypeHandler());
register(JdbcType.CLOB, new ClobTypeHandler());
register(JdbcType.LONGVARCHAR, new StringTypeHandler());
register(JdbcType.NVARCHAR, new NStringTypeHandler());
register(JdbcType.NCHAR, new NStringTypeHandler());
register(JdbcType.NCLOB, new NClobTypeHandler());

register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());
register(JdbcType.ARRAY, new ArrayTypeHandler());

register(BigInteger.class, new BigIntegerTypeHandler());
register(JdbcType.BIGINT, new LongTypeHandler());

register(BigDecimal.class, new BigDecimalTypeHandler());
register(JdbcType.REAL, new BigDecimalTypeHandler());
register(JdbcType.DECIMAL, new BigDecimalTypeHandler());
register(JdbcType.NUMERIC, new BigDecimalTypeHandler());

register(InputStream.class, new BlobInputStreamTypeHandler());
register(Byte[].class, new ByteObjectArrayTypeHandler());
register(Byte[].class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler());
register(Byte[].class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler());
register(byte[].class, new ByteArrayTypeHandler());
register(byte[].class, JdbcType.BLOB, new BlobTypeHandler());
register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler());
register(JdbcType.LONGVARBINARY, new BlobTypeHandler());
register(JdbcType.BLOB, new BlobTypeHandler());

register(Object.class, unknownTypeHandler);
register(Object.class, JdbcType.OTHER, unknownTypeHandler);
register(JdbcType.OTHER, unknownTypeHandler);

register(Date.class, new DateTypeHandler());
register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());
register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());
register(JdbcType.TIMESTAMP, new DateTypeHandler());
register(JdbcType.DATE, new DateOnlyTypeHandler());
register(JdbcType.TIME, new TimeOnlyTypeHandler());

register(java.sql.Date.class, new SqlDateTypeHandler());
register(java.sql.Time.class, new SqlTimeTypeHandler());
register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());

register(String.class, JdbcType.SQLXML, new SqlxmlTypeHandler());

register(Instant.class, new InstantTypeHandler());
register(LocalDateTime.class, new LocalDateTimeTypeHandler());
register(LocalDate.class, new LocalDateTypeHandler());
register(LocalTime.class, new LocalTimeTypeHandler());
register(OffsetDateTime.class, new OffsetDateTimeTypeHandler());
register(OffsetTime.class, new OffsetTimeTypeHandler());
register(ZonedDateTime.class, new ZonedDateTimeTypeHandler());
register(Month.class, new MonthTypeHandler());
register(Year.class, new YearTypeHandler());
register(YearMonth.class, new YearMonthTypeHandler());
register(JapaneseDate.class, new JapaneseDateTypeHandler());

// issue #273
register(Character.class, new CharacterTypeHandler());
register(char.class, new CharacterTypeHandler());
}

/**
* 为枚举类{@link Enum}设置默认的{@link TypeHandler}.默认是{@link EnumTypeHandler}
* Set a default {@link TypeHandler} class for {@link Enum}.
* A default {@link TypeHandler} is {@link org.apache.ibatis.type.EnumTypeHandler}.
* @param typeHandler a type handler class for {@link Enum}
* @since 3.4.5
*/
public void setDefaultEnumTypeHandler(Class<? extends TypeHandler> typeHandler) {
this.defaultEnumTypeHandler = typeHandler;
}

/**
* 是否存在对应 {@link @javaType} 的 {@link TypeHandler},直接调用{@link #hasTypeHandler(Class, JdbcType)}
* @param javaType
* @return
*/
public boolean hasTypeHandler(Class<?> javaType) {
return hasTypeHandler(javaType, null);
}

/**
* 是否存在对应{@link @javaTypeReference}的{@link TypeHandler},直接调用{@link #hasTypeHandler(TypeReference, JdbcType)},
* 第二个参数{@link @jdbcType}为null
* @param javaTypeReference
* @return
*/
public boolean hasTypeHandler(TypeReference<?> javaTypeReference) {
return hasTypeHandler(javaTypeReference, null);
}

/**
* 是否存在对应 {@link @javaType} 和 {@link @jdbcType} 的 {@link TypeHandler}
* <p>
* 先判断{@link @javaType} 是否为null,若为null,直接返回false。
* 再尝试调用{@link #getTypeHandler(Type, JdbcType)}获取TypeHandler不为null返回true
* </p>
*/
public boolean hasTypeHandler(Class<?> javaType, JdbcType jdbcType) {
return javaType != null && getTypeHandler((Type) javaType, jdbcType) != null;
}

/**
* 是否存在对应 {@link @javaTypeReference} 和 {@link @jdbcType} 的 {@link TypeHandler}
* <p>
* 先判断{@link @javaTypeReference} 是否为null,若为null,直接返回false。
* 再尝试调用{@link #getTypeHandler(TypeReference, JdbcType)}获取TypeHandler不为null返回true
* </p>
*/
public boolean hasTypeHandler(TypeReference<?> javaTypeReference, JdbcType jdbcType) {
return javaTypeReference != null && getTypeHandler(javaTypeReference, jdbcType) != null;
}

/**
* 获取TypeHandler实例
* <p>
* 从{@link #allTypeHandlersMap} 中获取对应{@link @handlerType}的{@link @handlerType}实例
* </p>
*/
public TypeHandler<?> getMappingTypeHandler(Class<? extends TypeHandler<?>> handlerType) {
return allTypeHandlersMap.get(handlerType);
}

/**
* 获取TypeHandler实例
* <p>
* 将{@link @type}强转为{@link Type},然后调用{@link #getTypeHandler(Type, JdbcType)},第二个参数{@link @jdbcType}设置成null
* </p>
*/
public <T> TypeHandler<T> getTypeHandler(Class<T> type) {
return getTypeHandler((Type) type, null);
}

/**
* 获取TypeHandler实例
* <p>
* 直接调用{@link #getTypeHandler(TypeReference, JdbcType)},第二个参数{@link @jdbcType}设置成null
* </p>
*/
public <T> TypeHandler<T> getTypeHandler(TypeReference<T> javaTypeReference) {
return getTypeHandler(javaTypeReference, null);
}

/**
* 获取TypeHandler实例
* <p>
* 从{@link #jdbcTypeHandlerMap}中获取对应{@link @jdbcType}
* </p>
*/
public TypeHandler<?> getTypeHandler(JdbcType jdbcType) {
return jdbcTypeHandlerMap.get(jdbcType);
}

/**
* 获取 TypeHandler
* <p>
* 将 {@link @type} 转换 {@link Type} 类型,然后调用 {@link TypeHandlerRegistry#getTypeHandler(Class, JdbcType)}
* </p>
*/
public <T> TypeHandler<T> getTypeHandler(Class<T> type, JdbcType jdbcType) {
return getTypeHandler((Type) type, jdbcType);
}

/**
* 获取 TypeHandler
* <p>
* 调用{@link @javaTypeReference}的{@link TypeReference#getRawType()}得到子类声明的对 T 泛型的声明的类型,
* 然后传给{@link #getTypeHandler(Type, JdbcType)}得到对应的TypeHandler
* </p>
*/
public <T> TypeHandler<T> getTypeHandler(TypeReference<T> javaTypeReference, JdbcType jdbcType) {
return getTypeHandler(javaTypeReference.getRawType(), jdbcType);
}

/**
* 根据 {@link @type} 和 {@link @jdbcType} 获取对应的 {@link TypeHandler}
*/
@SuppressWarnings("unchecked")
private <T> TypeHandler<T> getTypeHandler(Type type, JdbcType jdbcType) {
// {@link ParamMap)是一个HashMap<String,Object>的子类,它重写了get方法,使得如果尝试获取它没有的key,将会抛出{@link BindingException}
if (ParamMap.class.equals(type)) {
return null;
}
// 获取JdbcType、TypeHandler映射关系的map
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = getJdbcHandlerMap(type);
TypeHandler<?> handler = null;
if (jdbcHandlerMap != null) {
// 获取对应jdbcType的TypeHandler
handler = jdbcHandlerMap.get(jdbcType);
// 如果没有拿到,调用获取jdbcType为null值情况的TypeHandler
if (handler == null) {
handler = jdbcHandlerMap.get(null);
}
/*
* 还是没有拿到,就由Mybatis自己选择一个TypeHandler:
* 如果有多个不同类型的TypeHandler就无法选择TypeHandler,只能返回null;
* 但是如果只有一个类型的TypeHandler,但有多个同类型的TypeHandler实例,就取最后一个实例
*/
if (handler == null) {
// #591
handler = pickSoleHandler(jdbcHandlerMap);
}
}
// type drives generics here
// 就算handler=null,也不会抛出空指针或者转换异常
return (TypeHandler<T>) handler;
}

/**
* 获取JdbcType、TypeHandler映射关系的map
* <p>
* 先将{@link @type}传入从{@link #typeHandlerMap}中获取JdbcType、TypeHandler映射关系的map。如果找到就返回出去。
* 如果没有获取到,判断是不是枚举类,还是普通java类。
* </p>
*/
private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMap(Type type) {
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = typeHandlerMap.get(type);
// 空TypeHandler标识返回null也是符合场景的。
if (NULL_TYPE_HANDLER_MAP.equals(jdbcHandlerMap)) {
return null;
}
// 没有找到该类的JdbcType、TypeHandler映射关系Map 而且 {@link @type} 是 Class类,
if (jdbcHandlerMap == null && type instanceof Class) {
Class<?> clazz = (Class<?>) type;
// 属于枚举类型
if (Enum.class.isAssignableFrom(clazz)) {
// clazz若是枚举类型,clazz.getSuperclass()就得到java.lang.Enum,因为枚举类型不能extends,但是可以implement
// 下面代码如果属于内部类,就会得到java.lang.Enum
Class<?> enumClass = clazz.isAnonymousClass() ? clazz.getSuperclass() : clazz;
// 从枚举类的接口获取JdbcType、TypeHandler映射关系的map
jdbcHandlerMap = getJdbcHandlerMapForEnumInterfaces(enumClass, enumClass);
// 还是没有找到的话,就用defaultEnumTypeHandler的实例对象作为对应enumClass的TypeHandler
if (jdbcHandlerMap == null) {
register(enumClass, getInstance(enumClass, defaultEnumTypeHandler));
return typeHandlerMap.get(enumClass);
}
} else {
// 尝试通过获取父类去获取JdbcType、TypeHandler映射关系Map
jdbcHandlerMap = getJdbcHandlerMapForSuperclass(clazz);
}
}
// 没有JdbcType、TypeHandler映射关系Map时,就用NULL_TYPE_HANDLER_MAP作为对应type的JdbcType、TypeHandler映射关系Map
typeHandlerMap.put(type, jdbcHandlerMap == null ? NULL_TYPE_HANDLER_MAP : jdbcHandlerMap);
return jdbcHandlerMap;
}

/**
* 从枚举类的接口获取JdbcType、TypeHandler映射关系的map
* <p>
* 通过递归该方法深入{@link @clazz}的所有接口,若找到{@link @clazz}接口对应的JdbcType、TypeHandler映射关系map【{@link @jdbcHandlerMap}】,
* 就会根据{@link @jdbcHandlerMap}构建出{@link @enumClazz}对应的JdbcType、TypeHandler映射关系map。
* 注意一下,只会找出第一个匹配的JdbcType、TypeHandler映射关系map赋值给{@link @jdbcHandlerMap}。若还是没有找到JdbcType、TypeHandler映射关系map,就会返回null
* </p>
*/
private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMapForEnumInterfaces(Class<?> clazz, Class<?> enumClazz) {
// 获取该枚举类所实现的所有接口
for (Class<?> iface : clazz.getInterfaces()) {
// 尝试通过接口类获取JdbcType、TypeHandler映射关系的map
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = typeHandlerMap.get(iface);
// 如果还是没有找到,通过递归的方式,深入这个接口中看看还有没有继承接口,从那些接口里尝试获取JdbcType、TypeHandler映射关系的map
if (jdbcHandlerMap == null) {
jdbcHandlerMap = getJdbcHandlerMapForEnumInterfaces(iface, enumClazz);
}
// 找到了与接口对应的JdbcType、TypeHandler映射关系map后
if (jdbcHandlerMap != null) {
// Found a type handler regsiterd to a super interface
// 构建一个新的JdbcType、TypeHandler映射关系map
HashMap<JdbcType, TypeHandler<?>> newMap = new HashMap<>();
/*
* 将jdbcHandlerMap的元素添加给newMap:
* 将jdbcHandlerMap的key作为newMap的key,
* 传入enumClazz以及通过jdbcHandlerMap的value获取value的Class来构建一个对应该枚举类的TypeHandler对象作为value
*/
for (Entry<JdbcType, TypeHandler<?>> entry : jdbcHandlerMap.entrySet()) {
// Create a type handler instance with enum type as a constructor arg
newMap.put(entry.getKey(), getInstance(enumClazz, entry.getValue().getClass()));
}
// 找到了第一个就直接返回
return newMap;
}
}
return null;
}

/**
* 通过获取父类去获取JdbcType、TypeHandler映射关系Map
* <p>
* 通过递归{@link @clazz}的父类,获取第一个对应父类的JdbcType、TypeHandler映射关系Map
* </p>
*/
private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMapForSuperclass(Class<?> clazz) {
Class<?> superclass = clazz.getSuperclass();
// 没有获取到父类 或者 递归父类去获取JdbcType、TypeHandler映射关系Map,都到了Object,返回null也是理所当然啦
if (superclass == null || Object.class.equals(superclass)) {
return null;
}
// 只会找出第一个匹配的JdbcType、TypeHandler映射关系map,
// 就算真的有两个匹配的JdbcType、TypeHandler映射关系map,也不会合并且其JdbcType、TypeHandler映射关系map
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = typeHandlerMap.get(superclass);
if (jdbcHandlerMap != null) {
return jdbcHandlerMap;
} else {
// 递归父类
return getJdbcHandlerMapForSuperclass(superclass);
}
}

/**
* 选择唯一的TypeHandler
* <p>
* 如果有多个不同类型的TypeHandler就无法选择TypeHandler,只能返回null;
* 但是如果只有一个类型的TypeHandler,但有多个同类型的TypeHandler实例,就取最后一个实例
* </p>
* @param jdbcHandlerMap
* @return
*/
private TypeHandler<?> pickSoleHandler(Map<JdbcType, TypeHandler<?>> jdbcHandlerMap) {
TypeHandler<?> soleHandler = null;
for (TypeHandler<?> handler : jdbcHandlerMap.values()) {
if (soleHandler == null) {
soleHandler = handler;
} else if (!handler.getClass().equals(soleHandler.getClass())) {
// More than one type handlers registered.
// 不只一个TypeHandler类型的情况下
return null;
}
}
return soleHandler;
}

public TypeHandler<Object> getUnknownTypeHandler() {
return unknownTypeHandler;
}

/**
* 注册 jdbcType 对应的 TypeHandler
* <p>
* 直接调用以{@link @jdbcType}作为key 和 {@link @handler}作为value加入到{@link #jdbcTypeHandlerMap}中
* </p>
* @param jdbcType
* @param handler
*/
public void register(JdbcType jdbcType, TypeHandler<?> handler) {
jdbcTypeHandlerMap.put(jdbcType, handler);
}

//
// REGISTER INSTANCE
//

// Only handler

/**
* 注册TypeHandler
* <ol>
* <li>先尝试获取注解{@link MappedTypes}声明的类来调用{@link #register(Class, TypeHandler)}进行注册</li>
* <li>再尝试将{@link @typeHandler}转换成{@link TypeReference},从而获取到声明的泛型类型
* 来调用{@link #register(Class, TypeHandler)}进行注册</li>
* <li>都没有找到对应的java类型,就把javaType设置为null,调用{@link #register(Class, TypeHandler)}进行注册</li>
* </ol>
*/
@SuppressWarnings("unchecked")
public <T> void register(TypeHandler<T> typeHandler) {
// 一个标记,当注册了handledType就会变成true
boolean mappedTypeFound = false;
// 根据注解MappedType注册TypeHandler
MappedTypes mappedTypes = typeHandler.getClass().getAnnotation(MappedTypes.class);
if (mappedTypes != null) {
for (Class<?> handledType : mappedTypes.value()) {
register(handledType, typeHandler);
mappedTypeFound = true;
}
}
// 根据TypeReference声明的泛型类型注册TypeHandler
// @since 3.1.0 - try to auto-discover the mapped type
if (!mappedTypeFound && typeHandler instanceof TypeReference) {
try {
TypeReference<T> typeReference = (TypeReference<T>) typeHandler;
register(typeReference.getRawType(), typeHandler);
mappedTypeFound = true;
} catch (Throwable t) {
// 可能用户定义的类型引用具有不同的类型,并且不可赋值,所以忽略它
// maybe users define the TypeReference with a different type and are not assignable, so just ignore it
}
}
// 都没有找到对应的java类型,就当作null进行注册。
if (!mappedTypeFound) {
register((Class<T>) null, typeHandler);
}
}

// java type + handler

/**
* 注册 javaType -- TypeHandle
* 将{@link @javaType} 强转为 {@link Type}后,调用 {@link TypeHandlerRegistry#register(Type, TypeHandler)}
*/
public <T> void register(Class<T> javaType, TypeHandler<? extends T> typeHandler) {
register((Type) javaType, typeHandler);
}

/**
* 注册 javaType -- TypeHandle
* <p>
* 获取{@link @typeHandler}的{@link MappedJdbcTypes}注解信息赋值给{@link @mappedJdbcTypes},
* 在{@link @mappedJdbcTypes}不为null的情况下,遍历@mappedJdbcType所支持的jdbcType,
* 对其调用 {@link TypeHandlerRegistry#register(Class, JdbcType, Class)} 注册,再判断是否支持null的jdbcType,
* 支持的将null作为{@link TypeHandlerRegistry#register(Class, JdbcType, Class)}的第二参数进行调用;
* 否则,直接将null作为{@link TypeHandlerRegistry#register(Class, JdbcType, Class)}的第二参数进行调用
* </p>
*/
private <T> void register(Type javaType, TypeHandler<? extends T> typeHandler) {
MappedJdbcTypes mappedJdbcTypes = typeHandler.getClass().getAnnotation(MappedJdbcTypes.class);
if (mappedJdbcTypes != null) {
for (JdbcType handledJdbcType : mappedJdbcTypes.value()) {
register(javaType, handledJdbcType, typeHandler);
}
if (mappedJdbcTypes.includeNullJdbcType()) {
register(javaType, null, typeHandler);
}
} else {
register(javaType, null, typeHandler);
}
}

/**
* 注册 TypeHandler
* <p>
* 获取{@link @javaTypeReference}所声明的泛型类型,调用{@link #register(Class, TypeHandler)}进行注册
* </p>
*/
public <T> void register(TypeReference<T> javaTypeReference, TypeHandler<? extends T> handler) {
register(javaTypeReference.getRawType(), handler);
}

// java type + jdbc type + handler

/**
* 注册TypeHandler
* <p>
* 将{@link @type}强转成{@link Type},调用{@link #register(Type, JdbcType, TypeHandler)}进行注册
* </p>
*/
// Cast is required here
@SuppressWarnings("cast")
public <T> void register(Class<T> type, JdbcType jdbcType, TypeHandler<? extends T> handler) {
register((Type) type, jdbcType, handler);
}

/**
* 注册 javaType -- jdbcType -- TypeHandler
* <p>
* 先从 {@link TypeHandlerRegistry#typeHandlerMap} 中获取{@link @javaType}对应的 JdbcType、TypeHandler映射关系的map
* 并赋值给{@link @map},然后将{@link @jdbcType}作为key和{@link @handler}作为value设置到{@link @map}。
* 简单来说就是合并原有的,新建没有的。
* 最后还会获取{@link @handler}的Class类作为key,{@link @handler}作为value设置到{@link #allTypeHandlersMap}中
* </p>
* <p>
* 只要{@link @map} 是 null,或者是一个{@link TypeHandlerRegistry#NULL_TYPE_HANDLER_MAP}都会对{@link @map}重新实例化
* 一个新的{@link HashMap}并调用加入到 {@link #typeHandlerMap} 中。
* </p>
*/
private void register(Type javaType, JdbcType jdbcType, TypeHandler<?> handler) {
if (javaType != null) {
Map<JdbcType, TypeHandler<?>> map = typeHandlerMap.get(javaType);
if (map == null || map == NULL_TYPE_HANDLER_MAP) {
map = new HashMap<>();
}
map.put(jdbcType, handler);
typeHandlerMap.put(javaType, map);
}
allTypeHandlersMap.put(handler.getClass(), handler);
}

//
// REGISTER CLASS
//

// Only handler type

/**
* 注册TypeHandler
* <p>
* 通过注解{@link MappedTypes}获取{@link @typeHandlerClass}能处理的java类型,逐一调用{@link #register(Class, Class)}进行注册,
* 没有注册到指定类型+TypeHandler映射关系时,用null当作javaTypeClass参数,调用{@link #getInstance(Class, Class)}得到TypeHandler的实例,
* 然后调用{@link #register(TypeHandler)}进行注册。
* </p>
*/
public void register(Class<?> typeHandlerClass) {
boolean mappedTypeFound = false;
MappedTypes mappedTypes = typeHandlerClass.getAnnotation(MappedTypes.class);
if (mappedTypes != null) {
for (Class<?> javaTypeClass : mappedTypes.value()) {
register(javaTypeClass, typeHandlerClass);
mappedTypeFound = true;
}
}
if (!mappedTypeFound) {
register(getInstance(null, typeHandlerClass));
}
}

// java type + handler type

/**
* 注册TypeHandler
* <p>
* 调用{@link Resources#classForName(String)}获取{@link @javaTypeClassName}和{@link @typeHandlerClassName}的Class,
* 再调用{@link #register(Class, Class)}
* </p>
*/
public void register(String javaTypeClassName, String typeHandlerClassName) throws ClassNotFoundException {
register(Resources.classForName(javaTypeClassName), Resources.classForName(typeHandlerClassName));
}

/**
* 注册TypeHandler
* <p>
* 传入{@link @javaTypeClass}和{@link @typeHandlerClass}到{@link #getInstance(Class, Class)}中得到TypeHandler的实例对象,
* 再调用{@link #register(TypeHandler)}进行注册
* </p>
*/
public void register(Class<?> javaTypeClass, Class<?> typeHandlerClass) {
register(javaTypeClass, getInstance(javaTypeClass, typeHandlerClass));
}

// java type + jdbc type + handler type

/**
* 注册TypeHandler
* <p>
* 传入{@link @javaTypeClass}和{@link @typeHandlerClass}到{@link #getInstance(Class, Class)}中得到TypeHandler的实例对象,
* 再调用{@link #register(Type, JdbcType, TypeHandler)}进行注册
* </p>
*/
public void register(Class<?> javaTypeClass, JdbcType jdbcType, Class<?> typeHandlerClass) {
register(javaTypeClass, jdbcType, getInstance(javaTypeClass, typeHandlerClass));
}

// Construct a handler (used also from Builders)

/**
* 创建TypeHandler实例对象
* <p>
* 当{@link @javaTypeClass}不为null,会尝试通过带 Class 参数的构造方法进行实例化TypeHandler对象。
* 如果没有该构造方法,就通过无参构造方法实例化TypeHandler对象。
* </p>
*/
@SuppressWarnings("unchecked")
public <T> TypeHandler<T> getInstance(Class<?> javaTypeClass, Class<?> typeHandlerClass) {
if (javaTypeClass != null) {
try {
/*
* 尝试通过带 Class 参数的构造方法进行实例化TypeHandler对象。因为没有检查是否存在某个构造函数的方法,所以
* 使用捕捉异常的方式解决.
*/
Constructor<?> c = typeHandlerClass.getConstructor(Class.class);
return (TypeHandler<T>) c.newInstance(javaTypeClass);
} catch (NoSuchMethodException ignored) {
// ignored
} catch (Exception e) {
throw new TypeException("Failed invoking constructor for handler " + typeHandlerClass, e);
}
}
try {
// 通过无参构造方法实例化TypeHandler
Constructor<?> c = typeHandlerClass.getConstructor();
return (TypeHandler<T>) c.newInstance();
} catch (Exception e) {
throw new TypeException("Unable to find a usable constructor for " + typeHandlerClass, e);
}
}

// scan

/**
* 扫描包中的 {@link TypeHandler} 的子类,并 调用 {@link TypeHandlerRegistry#register(TypeHandler)}
* @param packageName
*/
public void register(String packageName) {
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
resolverUtil.find(new ResolverUtil.IsA(TypeHandler.class), packageName);
Set<Class<? extends Class<?>>> handlerSet = resolverUtil.getClasses();
for (Class<?> type : handlerSet) {
//Ignore inner classes and interfaces (including package-info.java) and abstract classes
if (!type.isAnonymousClass() && !type.isInterface() && !Modifier.isAbstract(type.getModifiers())) {
register(type);
}
}
}

// get information

/**
* 获取所有已注册的TypeHandler
* Gets the type handlers.
*
* @return the type handlers
* @since 3.2.2
*/
public Collection<TypeHandler<?>> getTypeHandlers() {
return Collections.unmodifiableCollection(allTypeHandlersMap.values());
}

}