mybatis源碼學習之——內部處理流程

接下來,我們按照之前寫的測試用例,使用debug來梳理一下mybatis的工作流程,測試用例如下:

package com.mybatis.mine;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.io.InputStream;

public class MineTest1 {

    @Test
    public void test01() throws IOException {
      String resource = "com/mybatis/mine/mybatis-config.xml";
      InputStream inputStream = Resources.getResourceAsStream(resource);
      SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
      SqlSession sqlSession = sqlSessionFactory.openSession();
      UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
      User user = userMapper.selectUser("10");
      System.out.println(user);
    }
}

首先我們來跟蹤SqlSessionFactory的創建:SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

經過debug跟蹤,我們會發現這個流程的主要步驟如下:

org.apache.ibatis.session.SqlSessionFactoryBuilder#build(java.io.InputStream)    //使用SqlSessionFactoryBuilder的build
   >org.apache.ibatis.session.SqlSessionFactoryBuilder#build(java.io.InputStream, java.lang.String, java.util.Properties) 
          >org.apache.ibatis.builder.xml.XMLConfigBuilder#parse    //加載配置文件,獲取configuration對象
             >org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration
                 >org.apache.ibatis.builder.xml.XMLConfigBuilder#mapperElement  //加載映射器
                     >org.apache.ibatis.session.Configuration#addMapper
                       >org.apache.ibatis.binding.MapperRegistry#addMapper
                           >org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#parse   //Annotation方式解析
    >org.apache.ibatis.session.SqlSessionFactoryBuilder#build(org.apache.ibatis.session.Configuration)    //生成SqlSessionFactory

也就是說在這裏,mybatis主要做了加載配置文件、加載映射器、生成SqlSessionFactory等主要操作。

接下來我們來SqlSession的獲取:SqlSession sqlSession = sqlSessionFactory.openSession();

org.apache.ibatis.session.SqlSessionFactory#openSession()   //獲取SqlSession
    >org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource     
        >org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#getTransactionFactoryFromEnvironment   //獲取 TransactionFactory
            >org.apache.ibatis.transaction.TransactionFactory#newTransaction(javax.sql.DataSource, org.apache.ibatis.session.TransactionIsolationLevel, boolean)   //獲取事務
                >org.apache.ibatis.session.Configuration#newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType)  // 生成Executor
                    >org.apache.ibatis.session.defaults.DefaultSqlSession   //new DefaultSqlSession() 

對於這一步,mybatis主要做的工作就是生成事務、創建執行器、最後生成SqlSession實例

對於UserMapper userMapper = sqlSession.getMapper(UserMapper.class);我們就不多贅述了,這個主要是從第一步的MapperRegistry中獲取相應的Mapper

最後我們來看下具體的數據庫操作流程:

org.apache.ibatis.binding.MapperProxy#invoke    //動態代理
    >org.apache.ibatis.binding.MapperMethod#execute
       >org.apache.ibatis.session.SqlSession#selectOne(java.lang.String, java.lang.Object)    //進行查詢
          >org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
             >org.apache.ibatis.session.Configuration#getMappedStatement(java.lang.String)  //獲取MappedStatement
                >org.apache.ibatis.session.defaults.DefaultSqlSession#wrapCollection    //解析參數
                   >org.apache.ibatis.executor.BaseExecutor#query()  //真正的查詢處理
                      >org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
                          >org.apache.ibatis.executor.BaseExecutor#doQuery
                              >org.apache.ibatis.session.Configuration#newStatementHandler   //生成StatementHandler
                                  >org.apache.ibatis.executor.statement.StatementHandler#query  //使用StatementHandler進行查詢處理
                                     >java.sql.PreparedStatement#execute   //調用jdbc的execute方法
                                     >org.apache.ibatis.executor.resultset.ResultSetHandler#handleResultSets   //結果集處理

這一步mybatis首先通過動態代理,找到目標方法,然後使用相應的執行器進行數據庫操作。在這一步中做了幾點重要的處理:

  • 獲取目標方法
  • 生成MappedStatement
  • 裝載參數
  • 生成StatementHandler
  • 調用StatementHandler中相應的方法,進行數據庫操作
  • 結果集處理

以上便是mybatis一個完整的處理流程,希望對大家有所啓發。下面附兩張圖大致總結一下以上流程:

第一張圖描述了從SqlSessionFactory創建到獲取Mapper的一個流程:

第二張圖描述了mybatis數據庫操作的簡易流程:

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