Mybatis源碼分析(02)-配置文件解析概述

使用Mybatis操作數據庫

使用Mybatis操作數據庫的基本寫法如下:


	@Test
    public void testMybatis(){
        //1.加載配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        //建造者設計模式
        //2.解析配置文件,封裝成Configuration 創建DefaultSqlSessionFactory對象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        //3.生產了DefaultSqlsession實例對象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        
        //傳統方式,根statementid從map中獲取MappedStatement對象
        //List<Object> list = sqlSession.selectList("com.mybaits.test.AccountDao.findAll");
        //4.代理方式,得到代理類對象
        AccountDao accountDao = sqlSession.getMapper(AccountDao.class);  
        //5.完成crud
        List<Account>list = accountDao.findAll();
        ...
    }
}

SqlSession是應用程序和mybatis交互的核心接口,而創建SqlSession對象之前還有一系列的前序操作,包括:

  1. 加載配置文件,由Resources.getResourceAsStream()完成。應用程序需要提供給Mybatis的配置文件有核心配置文件(上面程序中的sqlMapConfig.xml,實際使用不一定是這個名稱),以及映射配置文件(一般會命名爲xxxMapper.xml),映射配置文件的路徑會配置在覈心配置文件的<mappers>標籤下,所以外部加載的時候只加載核心配置文件就夠了。在之後的解析過程中,核心配置文件大部分內容會被保存在全局唯一的Configuration對象中

  2. 創建SqlSessionFactoryBuilder對象,從應用程序的角度看,該對象完成了兩個任務:

    • 將配置文件解析爲Configuration對象

    • 創建SqlSessionFactory對象,將Configuration對象傳遞給SqlSessionFactory對象,並返回SqlSessionFactory對象

  3. SqlSessionFactory對象主要用於生產SqlSession

SqlSessionFactoryBuilder

使用SqlSessionFactoryBuilder的入口是SqlSessionFactoryBuilder.build()方法

具體實現如下:

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
  try {
    //創建XMLConfigBuilder,用於解析mybatis配置文件
    XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
    //解析配置文件得到Configuration對象,創建DefaultSqlSessionFactory對象
    return build(parser.parse());
  } catch (Exception e) {
    throw ExceptionFactory.wrapException("Error building SqlSession.", e);
  } finally {
    ErrorContext.instance().reset();
    try {
      inputStream.close();
    } catch (IOException e) {
      // Intentionally ignore. Prefer previous error.
    }
  }
}

而這個方法在返回時調用的build()方法實現如下:

public SqlSessionFactory build(Configuration config) {
  return new DefaultSqlSessionFactory(config);  
}

BaseBuilder

顯然,SqlSessionFactoryBuilder中的重點在配置文件解析上,回到最初的build()方法,裏面創建了一個XMLConfigBuilder對象,而XMLConfigBuilder對象繼承自BaseBuilder,事實上,在上一章提到的Mybatis整體架構中,核心處理層的配置解析,主要就是由BaseBuilder及其子類完成的。

查看BaseBuilder的繼承與依賴關係,如下圖所示:
在這裏插入圖片描述

BaseBuilder中定義了以下三個屬性:

public abstract class BaseBuilder {
  //configuration保存Mybatis中幾乎全部的配置信息,
  protected final Configuration configuration;
  //核心配置文件可以使用<typeAliases>標籤定義別名,別名會記錄在typeAliasRegistry對象中
  protected final TypeAliasRegistry typeAliasRegistry;
  //核心配置文件可以使用<typeHandlers>標籤添加自定義TypeHandler器,完成指定數據庫類型與Java類型的轉換
  //這些TypeHandler會記錄在typeHandlerRegistry中
  protected final TypeHandlerRegistry typeHandlerRegistry;
  ...

另外BaseBuilder中的parseExpression用於解析配置文件中的正則表達式,booleanValueOf,integerValueOf,stringSetValueOf方法,從定義上看,應該是用於轉換配置文件中的屬性值字符串的類型,並且在沒有配置屬性的時候就使用默認值。

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<>(Arrays.asList(value.split(",")));
}

此外,resolveAlias()方法用於解析別名,resolveTypeHandler()方法查找指定的TypeHandler對象。

resolveJdbcType(),resolveResultSetType(),resolveParameterMode()這幾個方法會將String轉換爲對應的JdbcType枚舉類型、ResultSetType枚舉類和ParameterMode枚舉類,此處不做贅述,之後還會提到。

XMLConfigBuilder

XMLConfigBuilder完成了解析核心配置文件的任務。在Mybatis的核心配置文件中,主要有以下幾種標籤:

  • properties 屬性

  • settings 設置

  • typeAliases 類型別名

  • typehandlers 類型處理器

  • objectFactory 對象工廠

  • plugins 插件

  • environments 環境

    • enviroment 環境變量
      • transactionManager 事務管理器
      • dataSource 數據源
  • databaseidProvider 數據庫廠商標識

  • mappers 映射器

    XMLConfigBuilder也比較清晰地定義了每個標籤的解析方法:
    在這裏插入圖片描述

進行解析的入口是XMLConfigBuilder.parse()方法,會調用XpathParser對象將根標籤進行解析,傳給XMLConfigBuilder.parseConfiguration()方法:

public Configuration parse() {
  //如果已解析,拋出BuilderException異常
  if (parsed) {
    throw new BuilderException("Each XMLConfigBuilder can only be used once.");
  }
  parsed = true;
  //parser是XpathParser解析器對象,讀取節點內數據
  parseConfiguration(parser.evalNode("/configuration"));
  return configuration;
}

XMLConfigBuilder.parseConfiguration()逐個對每個子標籤調用對應的解析方法,下一章中將重點關注XMLConfigBuilder.mapperElement()方法,該方法用於對mapper標籤進行解析。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章