Mybatis原始碼--BaseBuilder原始碼分析
阿新 • • 發佈:2018-12-21
1 概述
BaseBuilder家族的主要作用就是處理配置檔案的內容,包括mapper配置檔案和config檔案,在這裡我們有必要首先對其基類進行簡單地說明。
2 屬性
2.1 configuration
持有配置檔案物件,方便解析配置檔案後對資料進行設定。
2.2 typeAliasRegistry
類別名註冊器,裡面持有類別名和類的鍵值對。
2.3 typeHandlerRegistry
型別處理註冊器。我們來看一下型別處理註冊器裡面的詳細實現。
2.3.1 屬性
//JDBC型別和型別處理器的對映關係,這裡用到EnumMap,這個EnumMap的鍵必須是列舉類中的值 private final Map<JdbcType, TypeHandler<?>> JDBC_TYPE_HANDLER_MAP = new EnumMap<JdbcType, TypeHandler<?>>(JdbcType.class); //類,JDBC型別和型別處理器的對映關係 private final Map<Type, Map<JdbcType, TypeHandler<?>>> TYPE_HANDLER_MAP = new HashMap<Type, Map<JdbcType, TypeHandler<?>>>(); //如果類沒有對應的型別處理器就是用這個型別處理器 private final TypeHandler<Object> UNKNOWN_TYPE_HANDLER = new UnknownTypeHandler(this); //普通類和型別處理器的對映關係 private final Map<Class<?>, TypeHandler<?>> ALL_TYPE_HANDLERS_MAP = new HashMap<Class<?>, TypeHandler<?>>();
2.3.2 核心函式
(1) java type + handler
public <T> void register(Class<T> javaType, TypeHandler<? extends T> typeHandler) {
register((Type) javaType, typeHandler);
}
我們可以看見這個函式裡面將javaType進行向上轉型成Type型別後,然後呼叫了另一個函式。
private <T> void register(Type javaType, TypeHandler<? extends T> typeHandler) { //獲取handler對應的註解MappedJdbcTypes,這個註解標記了型別處理器對應的jdbcType MappedJdbcTypes mappedJdbcTypes = typeHandler.getClass().getAnnotation(MappedJdbcTypes.class); if (mappedJdbcTypes != null) { //遍歷jdbcType陣列,進行jdbc型別,java型別和型別處理器註冊 for (JdbcType handledJdbcType : mappedJdbcTypes.value()) { register(javaType, handledJdbcType, typeHandler); } //空型別註冊 if (mappedJdbcTypes.includeNullJdbcType()) { register(javaType, null, typeHandler); } } else { register(javaType, null, typeHandler); } }
可以看出來,最終都是呼叫瞭如下函式:
private void register(Type javaType, JdbcType jdbcType, TypeHandler<?> handler) { if (javaType != null) { //獲取java型別對應的jdbc型別和型別處理器 Map<JdbcType, TypeHandler<?>> map = TYPE_HANDLER_MAP.get(javaType); if (map == null) { map = new HashMap<JdbcType, TypeHandler<?>>(); //新增java型別和型別處理器的對映關係 TYPE_HANDLER_MAP.put(javaType, map); } //新增jdbc型別和型別處理器的對映關係 map.put(jdbcType, handler); } //新增型別處理的類和型別處理器對映關係 ALL_TYPE_HANDLERS_MAP.put(handler.getClass(), handler); }
(2) jdbcType + handler
public void register(JdbcType jdbcType, TypeHandler<?> handler) {
JDBC_TYPE_HANDLER_MAP.put(jdbcType, handler);
}
這個函式其實就是直接將jdbc型別和型別處理器的map中加入對映關係。 其餘的函式我們這裡就不進行進一步分析了,大同小異。
3 函式
上面我們分析了BaseBuilder的屬性,現在我們針對重要的函式進行分析。
3.1 將字串轉換成對應的資料型別
protected Pattern parseExpression(String regex, String defaultValue) {
return Pattern.compile(regex == null ? defaultValue : regex);
}
protected Boolean booleanValueOf(String value, Boolean defaultValue) {
return value == null ? defaultValue : Boolean.valueOf(value);
}
protected Integer integerValueOf(String value, Integer defaultValue) {
return value == null ? defaultValue : Integer.valueOf(value);
}
protected Set<String> stringSetValueOf(String value, String defaultValue) {
value = (value == null ? defaultValue : value);
return new HashSet<String>(Arrays.asList(value.split(",")));
}
3.2 根據別名獲取對應的jdbc型別
protected JdbcType resolveJdbcType(String alias) {
if (alias == null) {
return null;
}
try {
return JdbcType.valueOf(alias);
} catch (IllegalArgumentException e) {
throw new BuilderException("Error resolving JdbcType. Cause: " + e, e);
}
}
3.3 根據別名獲取結果集型別
protected ResultSetType resolveResultSetType(String alias) {
if (alias == null) {
return null;
}
try {
return ResultSetType.valueOf(alias);
} catch (IllegalArgumentException e) {
throw new BuilderException("Error resolving ResultSetType. Cause: " + e, e);
}
}
3.4 根據別名獲取引數型別
protected ParameterMode resolveParameterMode(String alias) {
if (alias == null) {
return null;
}
try {
return ParameterMode.valueOf(alias);
} catch (IllegalArgumentException e) {
throw new BuilderException("Error resolving ParameterMode. Cause: " + e, e);
}
}
我們檢視ParameterMode列舉類,可以看見引數型別有 IN, OUT, INOUT。 針對餘下的函式這裡就不詳細說明了,其實就是呼叫其屬性對應的函式。
後面繼續更新對Mybatis原始碼的分析,歡迎交流。