5、MyBatis中的設計模式
設計模式
我們都知道設計模式分為3類23種設計模式,Mybatis至少用到了以下的設計模式的使用
BUildeer構建者模式
Builder模式,屬於建立類模式
它的定義是"將一個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表 示。”一般來說,如果一個物件的構建比較複雜,超出了建構函式所能包含的範 圍,就可以使用工廠模式和Builder模式,相對於工廠模式會產出一個完整的產品,Builder應用於更加 複雜的物件的構建,甚至只會構建產品的一個部分,直白來說,就是使用多個簡單的物件一步一步構建 成一個複雜的物件
主要步驟:
- 將需要構建的目標類分成多個部件(電腦可以分為主機、顯示器、鍵盤、音箱等部件);
- 建立構建類;
- 依次建立部件;
- 將部件組裝成目標物件
// 建立目標類物件
public class Computer {
// 顯示器
private String displayer;
// 主機
private String mainUnit;
// 滑鼠
private String mouse;
// 鍵盤
private String keyboard;
}
// 建立構建類物件 public class ComputerBuilder { Computer computer = new Computer(); public void installDisplayer(String displayer) { computer.setDisplayer(displayer); } public void installMainUnit(String mianUnit) { computer.setMainUnit(mianUnit); } public void installMouse(String mouse) { computer.setMouse(mouse); } public void installKeyboard(String keyboard) { computer.setKeyboard(keyboard); } public Computer Builder() { return computer; } }
// 將部分類組裝 public static void main(String[] args) { ComputerBuilder computerBuilder = new ComputerBuilder(); computerBuilder.installDisplayer("顯萬器"); computerBuilder.installMainUnit("主機"); computerBuilder.installKeyboard("鍵盤"); computerBuilder.installMouse("滑鼠"); Computer computer = computerBuilder.Builder(); System.out.println(computer); }
Mybaits使用的構建者模式
SqlSessionFactory 的構建過程:Mybatis的初始化工作非常複雜,不是隻用一個建構函式就能搞定的。所以使用了建造者模式,使用了 大 量的Builder,進行分層構造,核心物件Configuration使用了 XmlConfigBuilder來進行構造
在Mybatis環境的初始化過程中,SqlSessionFactoryBuilder會呼叫XMLConfigBuilder讀取所有的 MybatisMapConfig.xml 和所有的 *Mapper.xml 檔案,構建 Mybatis 執行的核心物件 Configuration 對 象,然後將該Configuration物件作為引數構建一個SqlSessionFactory物件。
其中 XMLConfigBuilder 在構建 Configuration 物件時,也會呼叫 XMLMapperBuilder 用於讀取 *Mapper 檔案,而XMLMapperBuilder會使用XMLStatementBuilder來讀取和build所有的SQL語句。
在這個過程中,有一個相似的特點,就是這些Builder會讀取檔案或者配置,然後做大量的XpathParser 解析、配置或語法的解析、反射生成物件、存入結果快取等步驟,這麼多的工作都不是一個建構函式所 能包括的,因此大量採用了 Builder模式來解決
SqlSessionFactoryBuilder類根據不同的輸入引數來構建SqlSessionFactory這個工廠物件
工廠模式
在Mybatis中比如SqlSessionFactory使用的是工廠模式,該工廠沒有那麼複雜的邏輯,是一個簡單工廠 模式
簡單工廠模式(Simple Factory Pattern):又稱為靜態工廠方法(Static Factory Method)模式,它屬於創 建型模式。
在簡單工廠模式中,可以根據引數的不同返回不同類的例項。簡單工廠模式專⻔定義一個類來負責建立
其他類的例項,被建立的例項通常都具有共同的父類
Mybatis 體現:
Mybatis中執行Sql語句、獲取Mappers、管理事務的核心介面SqlSession的建立過程使用到了工廠模
式。有一個 SqlSessionFactory 來負責 SqlSession 的建立
SqlSessionFactory
可以看到,該Factory的openSession ()方法過載了很多個,分別支 持autoCommit、Executor、Transaction等引數的輸入,來構建核心的SqlSession物件。 在DefaultSqlSessionFactory的預設工廠實現裡,有一個方法可以看出工廠怎麼產出一個產品:
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
// 獲得 Environment 物件
final Environment environment = configuration.getEnvironment();
// 建立 Transaction 物件
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
// 建立 Executor 物件
final Executor executor = configuration.newExecutor(tx, execType);
// 建立 DefaultSqlSession 物件
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
// 如果發生異常,則關閉 Transaction 物件
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
這是一個openSession呼叫的底層方法,該方法先從configuration讀取對應的環境配置,然後初始化 TransactionFactory 獲得一個 Transaction 物件,然後通過 Transaction 獲取一個 Executor 物件,最 後通過configuration、Executor、是否autoCommit三個引數構建了 SqlSession
代理模式
代理模式(Proxy Pattern):給某一個物件提供一個代理,並由代理物件控制對原物件的引用。代理模式 的英文叫做Proxy,它是一種物件結構型模式,代理模式分為靜態代理和動態代理,我們來介紹動態代 理
Mybatis中實現:
代理模式可以認為是Mybatis的核心使用的模式,正是由於這個模式,我們只需要編寫Mapper.java接 口,不需要實現,由Mybati s後臺幫我們完成具體SQL的執行。
當我們使用Configuration的getMapper方法時,會呼叫mapperRegistry.getMapper方法,而該方法又 會呼叫 mapperProxyFactory.newInstance(sqlSession)來生成一個具體的代理:
非常典型的,該MapperProxy類實現了InvocationHandler介面,並且實現了該介面的invoke方法。通 過這種方式,我們只需要編寫Mapper.java介面類,當真正執行一個Mapper介面的時候,就會轉發給 MapperProxy.invoke方法,而該方法則會呼叫後續的 sqlSession.cud>executor.execute>prepareStatement 等一系列方法,完成 SQL 的執行和返回