1. 程式人生 > >Mybatis原始碼--BaseBuilder原始碼分析

Mybatis原始碼--BaseBuilder原始碼分析

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原始碼的分析,歡迎交流。