MyBatis架構圖


MyBatis架構

MyBatis依賴的jar不多,而且代碼行數也沒多少,其中使用了大量的設計模式,值得好好學習。下圖是MyBatis的一張架構圖,來自Java框架篇—Mybatis 入門

Mybatis的功能架構分為三層:

  • API接口層:提供給外部使用的接口API,開發人員通過這些本地API來操縱數據庫。接口層一接收到調用請求就會調用數據處理層來完成具體的數據處理。
  • 數據處理層:負責具體的SQL查找、SQL解析、SQL執行和執行結果映射處理等。它主要的目的是根據調用的請求完成一次數據庫操作。
  • 基礎支撐層:負責最基礎的功能支撐,包括連接管理、事務管理、配置加載和緩存處理,這些都是共用的東西,將他們抽取出來作為最基礎的組件。為上層的數據處理層提供最基礎的支撐。

MyBatis整個項目的包結構如下:

.
└── org
    └── apache
        └── ibatis
            ├── annotations
            ├── binding
            ├── builder
            ├── cache
            ├── cursor
            ├── datasource
            ├── exceptions
            ├── executor
            ├── io
            ├── jdbc
            ├── logging
            ├── mapping
            ├── parsing
            ├── plugin
            ├── reflection
            ├── scripting
            ├── session
            ├── transaction
            └── type
 

1.兵馬未動,日志先行

org.apache.ibatis.logging

org.apache.ibatis.logging.commons

org.apache.ibatis.logging.jdbc

org.apache.ibatis.logging.jdk14

org.apache.ibatis.logging.log4j

org.apache.ibatis.logging.log4j2

org.apache.ibatis.logging.nologging

org.apache.ibatis.logging.slf4j

org.apache.ibatis.logging.stdout

2.異常

org.apache.ibatis.exceptions

3.緩存

org.apache.ibatis.cache

org.apache.ibatis.cache.decorators

org.apache.ibatis.cache.impl

4.解析

org.apache.ibatis.parsing

xml解析,${} 格式的字符串解析

源碼分析可以參考http://www.cnblogs.com/sunzhenchao/p/3161093.html

5.類型處理器

org.apache.ibatis.type

實現java和jdbc中的類型之間轉換

源碼分析可以參考http://www.cnblogs.com/sunzhenchao/archive/2013/04/09/3009431.html

6.IO

org.apache.ibatis.io

通過類加載器在jar包中尋找一個package下滿足條件(比如某個接口的子類)的所有類

7.反射

org.apache.ibatis.reflection

org.apache.ibatis.reflection.factory

org.apache.ibatis.reflection.invoker

org.apache.ibatis.reflection.property

org.apache.ibatis.reflection.wrapper

可以參考MetaObjectTest來跟蹤調試,基本上用到了reflection包下所有的類


8.數據源

org.apache.ibatis.datasource

org.apache.ibatis.datasource.jndi

org.apache.ibatis.datasource.pooled

org.apache.ibatis.datasource.unpooled

9.事務

org.apache.ibatis.transaction

org.apache.ibatis.transaction.jdbc

org.apache.ibatis.transaction.managed

10.會話

org.apache.ibatis.session

org.apache.ibatis.session.defaults

11.jdbc單元測試工具

org.apache.ibatis.jdbc

12.構建

org.apache.ibatis.builder

org.apache.ibatis.builder.annotation

org.apache.ibatis.builder.xml

13.映射

org.apache.ibatis.mapping

14.腳本

org.apache.ibatis.scripting

org.apache.ibatis.scripting.defaults

org.apache.ibatis.scripting.xmltags

15.注解

org.apache.ibatis.annotations

16.綁定

org.apache.ibatis.binding

17.執行器

org.apache.ibatis.executor

org.apache.ibatis.executor.keygen

org.apache.ibatis.executor.loader

org.apache.ibatis.executor.loader.cglib

org.apache.ibatis.executor.loader.javassist

org.apache.ibatis.executor.parameter

org.apache.ibatis.executor.result

org.apache.ibatis.executor.resultset

org.apache.ibatis.executor.statement

18.插件

org.apache.ibatis.plugin



image002

注釋①

mybatis通過SqlSessionFactoryBuilder作為入口,通過傳入配置文件,使用了BaseBuilder實現類進行配置文件解析,具體實現類是XMLConfigBuilder,在這里mybatis對配置的項進行了全面解析,只不過不是所有的解析都放在了XMLConfigBuilder,XMLConfigBuilder解析了二級節點,並作為一個總入口,還有另外幾個類繼承了BaseBuilder,用於解析不同的配置。而解析到的配置項信息,基本都保存在了Configuration這個類,可以看到多處地方依賴到它。

之后通過配置獲取到SqlSessionFactory,可以看到SqlSessionFactoryBuilder提供了一個build方法,就是返回SqlSessionFactory的。

注釋②

而SqlSessionFactory只是一個接口,默認實現有DeaultSqlSessionFactory。通過SqlSessionFactory.openSession的幾個多態方法,可以獲取到SqlSession。

注釋③

而SqlSession也只是一個接口,怎么理解SqlSession呢,其實Session即是一次會話,假如我們把某次請求與數據庫連接Connection的交互,看成是一次會話,那就可以理解SqlSession了。SqlSession是請求與數據庫的一次交互,交互完成之后,Session則結束,但Session結束不代表數據庫連接也關閉,只是這次會話終止了,但是數據庫連接依舊是返回給連接池。

這里的SqlSession即是對一次交互信息的封裝,請求可以通過SqlSession的方法(如圖:CRUD )進行操作,而數據庫連接,依舊由SqlSessionFactory注入。

注釋②

如圖我們可以看到SqlSessionFactory獲取到TransactionFactory,一個事務的工廠類接口,而通過這個工廠具體實現類可以產生多個事務Transaction(具體參考ManagedTransactionFactory),Transaction抽象了一個方法getConnection,通過這個方法我們可以獲取到不同事務級別的connection。mybatis的代碼是這樣的:

ManagedTransaction.java

protected void openConnection() throws SQLException {
if (log.isDebugEnabled()) {
log.debug(“Opening JDBC Connection”);
}
this.connection = this.dataSource.getConnection();
if (this.level != null) {
this.connection.setTransactionIsolation(this.level.getLevel());
}
}

注釋④

這個時候可能大家覺得萬事俱備了,SqlSession都定義好了CRUD 方法了,那它也會幫忙將語句扔給Connection操作,其實不然。這里mybatis還抽象了接口Execute。

Execute才是真正將sql與Connection打交道的地方。

圖中我們可以看到Execute有四個實現類,通過名稱我們不難發現它們各自的用途,例如CachingExecutor.java,mybatis默認是有緩存的,就是通過這個類實現的。

還有一個點,每個Execute實現類中,都可以發現有這樣一個定義和構造方法

private Executor delegate;

public CachingExecutor(Executor delegate) {
this.delegate = delegate;
delegate.setExecutorWrapper(this);
}

所以這里我們也可以看到,其實Executor有個鏈結構,一步一步往下執行,所以在真正執行查詢時,外面是嵌套了一層CachingExecutor,證據在這里。

  1. public Executor newExecutor(Transaction transaction, ExecutorType executorType, boolean autoCommit) {
  2.   executorType = executorType == null ? defaultExecutorType : executorType;
  3.   executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
  4.   Executor executor;
  5.   if (ExecutorType.BATCH == executorType) {
  6.     executor = new BatchExecutor(this, transaction);
  7.   } else if (ExecutorType.REUSE == executorType) {
  8.     executor = new ReuseExecutor(this, transaction);
  9.   } else {
  10.     executor = new SimpleExecutor(this, transaction);
  11.   }
  12.   if (cacheEnabled) {
  13.     executor = new CachingExecutor(executor, autoCommit);
  14.   }
  15.   executor = (Executor) interceptorChain.pluginAll(executor);
  16.   return executor;
  17. }

在Execute中,還有更深層的執行邏輯,這個后面文章繼續分析。

轉載請注明出處:http://sukerz.scse.cn/index.php/2016/02/01/mybatis-framework/

 


免責聲明!

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



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