聊聊Mybatis的類型轉換注冊類TypeHandlerRegistry
上篇文章中我們說到TypeHandler是進行類型轉換的接口,它有針對不同的類型有很多實作類,TypeHandlerRegistry來進行統一管理
Mybatis初始化TypeHandler後,調用TypeHandlerRegistry的register()方法進行注冊,下面就看一下register()
注冊類型轉換處理器
ypeHandlerRegistry的register()方法:
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);
}
allTypeHandlersMap中儲存着所有TypeHandler類型和它對應的執行個體,除了這個register()方法,還可以根據@MappedJdbcTypes和@MappedTypes注解擷取資料,@MappedTypes配置配置TypeHandler接口與Java類型的集合,@MappedJdbcTypes配置TypeHandler接口與Jdbc類型的集合,TypeHandlerRegistry的構造方法中調用了很多注冊方法對不同jdbc類型選擇不同TypeHandler的執行個體來進行注冊
完成類型與TypeHandler執行個體的注冊後,mybatis會根據java類型和jdbc類型來查找對應的TypeHandler執行個體,調用方法是TypeHandlerRegistry的getTypeHandler()方法:
擷取類型處理器
TypeHandlerRegistry的getTypeHandler()方法:
private <T> TypeHandler<T> getTypeHandler(Type type, JdbcType jdbcType) {
if (ParamMap.class.equals(type)) {
return null;
}
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = getJdbcHandlerMap(type);
TypeHandler<?> handler = null;
if (jdbcHandlerMap != null) {
handler = jdbcHandlerMap.get(jdbcType);
if (handler == null) {
handler = jdbcHandlerMap.get(null);
}
if (handler == null) {
handler = pickSoleHandler(jdbcHandlerMap);
}
}
// type drives generics here
return (TypeHandler<T>) handler;
}
- 調用getJdbcHandlerMap()方法根據Java類型查找對應的TypeHandler集合
- 如果不為空,根據jdbcType擷取TypeHandler執行個體,如果找不到執行個體就使用null來擷取TypeHandler的執行個體
- 如果jdbcHandlerMap隻注冊了一個TypeHandler,就使用這個TypeHandler對應的執行個體
擷取jdbc類型對應的處理器
private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMap(Type type) {
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = typeHandlerMap.get(type);
if (NULL_TYPE_HANDLER_MAP.equals(jdbcHandlerMap)) { // 檢測是否為空集合辨別
return null;
}
if (jdbcHandlerMap == null && type instanceof Class) {
Class<?> clazz = (Class<?>) type;
if (Enum.class.isAssignableFrom(clazz)) { // 針對枚舉類型的處理
Class<?> enumClass = clazz.isAnonymousClass() ? clazz.getSuperclass() : clazz;
jdbcHandlerMap = getJdbcHandlerMapForEnumInterfaces(enumClass, enumClass);
if (jdbcHandlerMap == null) {
register(enumClass, getInstance(enumClass, defaultEnumTypeHandler));
return typeHandlerMap.get(enumClass);
}
} else {
// 查找父類關聯的TypeHandler集合,并将其作為clazz對應的TypeHandler集合
jdbcHandlerMap = getJdbcHandlerMapForSuperclass(clazz);
}
}
// 如果上述查找皆失敗,則以NULL_TYPE_HANDLER_MAP作為clazz對應的TypeHandler集合
typeHandlerMap.put(type, jdbcHandlerMap == null ?
NULL_TYPE_HANDLER_MAP : jdbcHandlerMap);
return jdbcHandlerMap;
}
- 先查找指定Java類型對應的TypeHandler集合
- 如果為空傳回null
- 初始化指定Java類型的TypeHandler集合
- 調用getJdbcHandlerMapForSuperclass()
private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMapForSuperclass(Class<?> clazz) {
Class<?> superclass = clazz.getSuperclass();
if (superclass == null || Object.class.equals(superclass)) {
return null; // 父類為Object或null則查找結束
}
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = typeHandlerMap.get(superclass);
if (jdbcHandlerMap != null) {
return jdbcHandlerMap;
} else {
return getJdbcHandlerMapForSuperclass(superclass);
}
}