MyBatis源碼分析-MyBatis初始化流程


  MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優秀的持久層框架。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可以對配置和原生Map使用簡單的 XML 或注解,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。如何新建MyBatis源碼工程請點擊MyBatis源碼分析-IDEA新建MyBatis源碼工程

  MyBatis初始化的過程也就是創建Configuration對象的過程,下面以XML方式為例說明MyBatis是如何完成初始化的(完整測試代碼點擊MyBatis源碼分析-SQL語句執行的完整流程)。

String resouce = "conf.xml";
InputStream is = Resources.getResourceAsStream(resouce);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = sqlSessionFactory.openSession();
user = session.selectOne("com.luoxn28.dao.UserDao.getById", 1);

  以上代碼經過了MyBatis初始化、創建SQLSession、執行SQL語句3個過程。根據conf.xml配置文件創建SqlSessionFactory對象,然后創建SqlSession對象,執行SQL語句。其中,MyBatis的初始化就發生在SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is)

       MyBatis初始化基本過程總結如下:SqlSessionFactoryBuilder根據傳入的數據流生成Configuration對象,然后根據Configuration對象創建默認的SqlSessionFactory實例。其中序列圖如下:

上圖的初始化過程經過以下的幾步:

  • 1. 調用SqlSessionFactoryBuilder對象的build(inputStream)方法;
  • 2. SqlSessionFactoryBuilder會根據輸入流inputStream等信息創建XMLConfigBuilder對象;
  • 3. SqlSessionFactoryBuilder調用XMLConfigBuilder對象的parse()方法;
  • 4. XMLConfigBuilder對象返回Configuration對象;
  • 5. SqlSessionFactoryBuilder根據Configuration對象創建一個DefaultSessionFactory對象;
  • 6. SqlSessionFactoryBuilder返回 DefaultSessionFactory對象給Client,供Client使用。

 

SqlSessionFactoryBuilder相關代碼:

public SqlSessionFactory build(InputStream inputStream) {
  return build(inputStream, null, null);
}
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
  try {
    // 1. 創建XMLConfigBuilder對象解析XML配置
    XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
    // 2. 將XML配置解析成Configuration對象,通過Configuration對象創建SqlSessionFactory
    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.
    }
  }
}
/**
 * 內部通過Configuration對象創建SqlSessionFactory,也可以通過Java API方式創建Configuration對象,
 * 然后調用該方法創建SqlSessionFactory
 */
public SqlSessionFactory build(Configuration config) {
  return new DefaultSqlSessionFactory(config);
}

 

創建Configuration對象過程

  接着上述的 MyBatis初始化基本過程討論,當SqlSessionFactoryBuilder執行build()方法,調用了XMLConfigBuilder的parse()方法,然后返回了Configuration對象。那么parse()方法是如何處理XML文件,生成Configuration對象的呢?

  1. XMLConfigBuilder會將XML配置文件的信息轉換為Document對象,而XML配置定義文件DTD轉換成XMLMapperEntityResolver對象,然后將二者封裝到XpathParser對象中,XpathParser的作用是提供根據Xpath表達式獲取基本的DOM節點Node信息的操作。如下圖所示:

  2. 之后XMLConfigBuilder調用parse()方法:會從XPathParser中取出 <configuration>節點對應的Node對象,然后解析此Node節點的子Node:properties, settings, typeAliases,typeHandlers, objectFactory, objectWrapperFactory, plugins, environments,databaseIdProvider, mappers等。

public Configuration parse() {
  if (parsed) {
    throw new BuilderException("Each XMLConfigBuilder can only be used once.");
  }
  parsed = true;
  parseConfiguration(parser.evalNode("/configuration"));
  return configuration;
}

private void parseConfiguration(XNode root) {
  try {
    //issue #117 read properties first
    propertiesElement(root.evalNode("properties"));
    Properties settings = settingsAsProperties(root.evalNode("settings"));
    loadCustomVfs(settings);
    typeAliasesElement(root.evalNode("typeAliases"));
    pluginElement(root.evalNode("plugins"));
    objectFactoryElement(root.evalNode("objectFactory"));
    objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
    reflectorFactoryElement(root.evalNode("reflectorFactory"));
    settingsElement(settings);
    // read it after objectFactory and objectWrapperFactory issue #631
    environmentsElement(root.evalNode("environments"));
    databaseIdProviderElement(root.evalNode("databaseIdProvider"));
    typeHandlerElement(root.evalNode("typeHandlers"));
    mapperElement(root.evalNode("mappers"));
  } catch (Exception e) {
    throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
  }
}

  解析出XML中對應的值后就設置到Configuration對象中,具體解析過程可以閱讀對應源代碼。Configuration對象創建好之后就會返回,並由此創建DefaultSqlSessionFactory對象。

  mapper.xml文件是在 mapperElement(root.evalNode("mappers")); 中解析的。

 

參考:

1、《深入理解mybatis原理》 Mybatis初始化機制詳解

2、MyBatis源碼分析-IDEA新建MyBatis源碼工程

3、MyBatis源碼分析-SQL語句執行的完整流程

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM