Mybatis源碼之核心流程分析

終于談到了Mybatis最核心的東西了,最核心的就是通過配置XML文件或注解中的SQL,直接調用接口就能執行配置好的SQL語句并封裝成對應的返回類型的數據。

先看一下Mybatis使用示例:

//創建Builder對象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//讀取配置文件IO流
InputStream is = Resources.getResourceAsStream("mybatis/mybatis-cfg.xml");
//解析IO流到內存Configuration對象中
SqlSessionFactory build = builder.build(is);
//獲取一個持久化會話對象
SqlSession openSession = build.openSession();
//通過SqlSession調用
List list = openSession.selectOne("com.test.mybatis.MybatisTest.official.dao.IUserDao.getUserInfo");
System.out.println("============"+list);
//通過接口對象調用
IUserDao dao = openSession.getMapper(IUserDao.class);
System.out.println(dao.getUserLimit());//關閉SqlSession
openSession.close();

雖然看起來使用非常簡單,但是內部構建這么一個ORM框架還是很艱難的,所以本章節會特別長

設計模式

照舊先來看一看設計模式

建造者模式(Builder Pattern)

使用多個簡單的對象一步一步構建成一個復雜的對象。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。

一個 Builder 類會一步一步構造最終的對象。該 Builder 類是獨立于其他對象的。

UML:

Builder:給出一個抽象接口,以規范產品對 象的各個組成成分的建造。這個接口規定要實 現復雜對象的哪些部分的創建,并不涉及具體 的對象部件的創建;

ConcreteBuilder:實現Builder接口,針對 不同的商業邏輯,具體化復雜對象的各部分的 創建。 在建造過程完成后,提供產品的實例;

Director:調用具體建造者來創建復雜對象的 各個部分,在指導者中不涉及具體產品的信息, 只負責保證對象各部分完整創建或按某種順序 創建;

Product:要創建的復雜對象。

建造者模式對齊工廠模式創建出來的對象要更加的復雜,適用于實例化對象頻繁改變的場景,適合流式編程。

但是現在流式編程是趨勢,所以使用建造者模式創建對象的框架會越來越多,下面會講到流式編程。

策略模式(Strategy Pattern)

一個類的行為或其算法可以在運行時更改。這種類型的設計模式屬于行為型模式。

在策略模式中,我們創建表示各種策略的對象和一個行為隨著策略對象改變而改變的 context 對象。策略對象改變 context 對象的執行算法。

應用最多的就是if else代碼當中

UML:

?

Context:算法調用者,使用setStrategy方法靈活的選擇策略(strategy);

Strategy:算法的統一接口;

ConcreteStrategy:算法的具體實現;

源碼分析

構建并解析XML文件

在使用的過程中都了解到了,首先就是將Mybatis的配置XML文件進行解析,解析后的數據都是存于Configuration對象當中,

先看一下Configuration這個類,單例,生命周期是應用級別,屬性太多這里就不全截圖出來了,大家可以自己下載源碼去查看,截圖如下:

但是在這個類中有幾個對象需先講一下:

MapperRegistry

mapper接口動態代理工廠類的注冊中心。在MyBatis中,通過mapperProxy實現 InvocationHandler接口,MapperProxyFactory用于生成動態代理的實例對象;

TypeAliasRegistry

所以別名存儲的地方,但是大家可以去看一下Configuration的構造方法,各類的默認參數都已經設置進去,不僅僅是Configuration的構造,在它自己的構造中將jdk自帶的一些類也加進去了,這就是為什么有些別名默認就有的原因:

這個類里面也是有個Map<String,Class<?>>的這樣的map用來儲存這些數據

mappedStatements

這個是所有SQL信息儲存的地方,使用的事繼承自HashMap的自定義類StrictMap,這個map的key值為mapper的XML的namespace加上select|update|delete|insert標簽的ID。具體的下面會談到。

SqlSource

mapper.xml文件中的sql語句會被解析成SqlSource對象,經過解析SqlSource包含的語 句最終僅僅包含?占位符,可以直接提交給數據庫執行;

TypeHandlerRegistry

是將數據庫中的類型轉換成JDK中的類型,進行對應,這個也有默認的集合,大家也可以去源碼里面看一下。

整體介紹

整體解析建造者Builder類關系圖:

使用的建造者圖解:

我們就跟著解析流程講解一下(在創建XMLConfigBuiler對象的時候會把Configuration對象創建出來):

進XMLConfigBuilder對象的parse方法看,執行了一個parseConfiguration(parser.evalNode("/configuration"));解析對象之前封裝的XNode節點數據;

有些并非很重要的方法就沒有標明,所以感興趣的可以去看一下。

解析properties標簽

解析完后會將所有的數據設置在configuration對象當中。

解析typeAliases標簽

解析plugin標簽

插件的使用這好像好沒有提到,等后面在說吧。

解析mappers標簽

這個算是解析文件里的一個比較中的東西

這時候開始使用XMLMapperBuilder建造者開始建造數據了:

我們看一下configurationElement方法:

這里的最后一個方法就開始了XMLStatementBuilder建造者開始建造了,看一些比較關鍵的地方

在創建MappedStatement對象時,使用的是流式編程

將數據全部加載完后,就是綁定工作空間了

在綁定方法中,如果namespace不是指定的接口全類名,那么就不會被添加到?mapperRegistry對象當中,這個對象就是用來跟接口做綁定的,進入到mapperRegistry的addMapper方法當中,

基本就是這么將動態代理跟namespace綁定的,構造XML的過程基本完結了,使用Mybatis的初始化已經完成,接下來就是使用持久化會話SqlSession這一塊了

創建SqlSession

SqlSession是Mybatis對外提供的一個重要接口,可以通過這個跟數據庫進行交互,或者創建接口代理對象,

UML:

創建一個默認的SqlSession工廠,這里用到了抽象工廠設計模式,之前為博客中提到了抽象工廠,那么這里就不細講了,

我們調用時創建出了一個默認的DefaultSqlSession對象,在之前的示例當中,我們可以直接調用selectList方法也能調用getMapper方法,其實直接使用SelectList方法是ibatis編程模型,當加入了getMapper方法后就是采用接口形式開發,這種開始模式比之前的ibatis開發模式要更為簡潔,并清楚業務。

我們先看一下原始的ibatis編程,即調用namespace+id方法

我們在看一下getMapper編程模式:

創建除了動態代理類之后,我們看一下代理類的實現:

這里的代理有一定的版本問題,由于JDK8支持在接口中寫方法主體,所以需做一層判斷才能執行正確的方法。

又是在invoke中執行的是invoke方法,所以在PlainMethodInvoker這個對象,執行的是mapperMethod.execute,

所以由此看出,getMapper也是基于ibatis編程模式開發。

SqlSession基本講完了,接下來就是Executor執行器了。

Executor執行器

這個用到是模板模式,我在AQS中談到的設計模式也是模板設計模式,模板模式-設計模式

BaseExecutor:抽象類,實現了executor接口的大部 分方法,主要提供了緩存管理和事務管理的能力,其他 子類需要實現的抽象方法為:doUpdate,doQuery等方法;

這個有四個對應的實現類:

SimpleExecutor:默認配置,使用PrepareStatement對象訪問數據庫,每次訪問都要創建新的 PrepareStatement對象;

ReuseExecutor:使用預編譯PrepareStatement對象訪問數據庫,訪問時,會重用緩存中的statement對象;

BatchExecutor:實現批量執行多條SQL語句的能力;

ClosedExecutor:異常執行器。

默認的方法為SimpleExecutor(在Configuration參數中有),之前看到是執行了Executor中的query方法,這里講一下:

進入到queryFormDatabase方法中:

doQuery方法中,發現多了Executor也并非執行,讓Handler去執行:

通過對SimpleExecutor doQuery()方法的解讀發現,Executor是個指揮官,它在調度三個Handler工作:

StatementHandler:它的作用是使用數據庫的Statement或PrepareStatement執行操作,啟承上啟下作用;

ParameterHandler:對預編譯的SQL語句進行參數設置,SQL語句中的的占位符“?”都對應 BoundSql.parameterMappings集合中的一個元素,在該對象中記錄了對應的參數名稱以及該參數的相關屬性

ResultSetHandler:對數據庫返回的結果集(ResultSet)進行封裝,返回用戶指定的實體類型;

StatementHadnler

BaseStatementHandler:所有子類的抽象 父類,定義了初始化statement的操作順序, 由子類實現具體的實例化不同的statement (模板模式);

RoutingStatementHandler:Excutor組件 真正實例化的子類,使用靜態代理模式, 根據上下文決定創建哪個具體實體類;

SimpleStatmentHandler :使用statement 對象訪問數據庫,無須參數化;

PreparedStatmentHandler :使用預編譯 PrepareStatement對象訪問數據庫;

CallableStatmentHandler :調用存儲過程;

在獲取到對應的Statement對象之后就是執行Statement并封裝結果集

隨著Executor執行器執行完畢,數據也就這樣執行出來了。

Mybatis大部分的核心知識基本都在這里,但是難免還是會有一些遺漏;后面遇到了就會做一些補充。

很多插件以及可擴展的方法接口等等,Mybatis發展這么多年,不可能在一段時間內知曉,還需潛心學習。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/537124.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/537124.shtml
英文地址,請注明出處:http://en.pswp.cn/news/537124.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mimakatz用法_兩步完成利用procdump64+mimikatz獲取win用戶密碼

使用procdump64mimikatz可實現從內存中獲取明文密碼工具鏈接&#xff1a;https://pan.baidu.com/s/1gNc9qLcNSNBohIVrAiqShw 密碼&#xff1a;fc38首先得先獲取到內存文件lsass.exe進程, 它用于本地安全和登陸策略,一般在進程管理器中能看到, 比如這樣1.導出lsass.exeprocdump6…

ios app提交之前需要哪幾個證書

1、遇到的問題 一款App在別人的機器上開發和發布&#xff0c;現在迭代更新和開發需要在一臺新mac機上開發和發布。&#xff08;使用同一個開發者賬號&#xff09;問題&#xff1a; 1.在新mac機器上開發并導入真機測試&#xff0c;是不是需要從別人的機器上面導處開發者證書、開…

Mybatis源碼之與Spring集成包

這次講講Mybatis與Spring的整合&#xff0c;作為兩款優秀的開源框架&#xff0c;被大眾廣泛使用&#xff0c;自然是需要強強聯合的。 使用示例 先看一下怎么使用&#xff0c;首先需要引用這兩款框架的jar包&#xff1a; <dependency>//spring-webmvc會自動去引入其他S…

hadoop主節點切換_hadoop2.0 HA的主備自動切換

在《hadoop2.0 QJM方式的HA的配置》一文中介紹了HA的配置&#xff0c;是通過手工進行主備切換的。本文在這基礎上&#xff0c;繼續介紹HA的主備自動切換(automatic failover)的配置。自動切換是通過配置zookeeper來實現的&#xff0c;關于zookeeper的安裝和配置&#xff0c;在這…

Mybatis源碼之插件模塊分析

總結完這個Mybatis的整體主要功能基本上就差不多完&#xff0c;還有一些細節的部分&#xff0c;后續都會記錄補充。 插件這個東西一般用的比較少&#xff0c;就算用的多的插件也算是PageHelper分頁插件&#xff1b; PageHelper官網&#xff1a;https://github.com/pagehelper…

AMD推出7nm高端顯卡Radeon VII,直指英偉達RTX 2080

顯卡戰爭已經發展到了2019年&#xff0c;并且變得比任何人預想的都要激烈。 CES 2019大會上&#xff0c;AMD發布了第一款消費級的 7nm GPU&#xff0c;取名&#xff1a;Radeon VII。據了解&#xff0c;這不是 AMD 的第一顆 7nm 處理器&#xff08;早期以 AI 運算為主的 Radeon …

電子繪本pdf_【孩子必看的】20本世界著名英文繪本 | PDF電子版+MP3音頻

原標題&#xff1a;【孩子必看的】20本世界著名英文繪本 | PDF電子版MP3音頻2 —6歲年齡段的孩子&#xff0c;自我意識逐漸萌芽&#xff0c;已經明白書是一種“特殊”的玩具&#xff0c;不在撕書、咬書、把書搬來搬去。這個階段他們記憶力超強&#xff0c;唐詩、三字經啥的&…

Spring集成Mybatis多數據源配置

既然在整理Mybatis那就把經常用的這個多數據源的筆記也整一下吧。 Spring集成Mybatis在之前就已經提到了。Spring集成Mybatis 集成Mybatis多數據源有兩種方式&#xff1a; 1、創建多個SqlSessionFactory&#xff0c;掃描每個SqlSessionFactoryBean對應的包&#xff0c;形成了…

Spring文件上傳

2019獨角獸企業重金招聘Python工程師標準>>> Spring文件上傳 1、所需依賴包&#xff1a;commons-fileupload-1.3.1.jar2、Maven配置文件pom.xml文件中加入依賴Jar包<dependency><groupId>commons-fileupload</groupId><artifactId>commons-…

中英離線翻譯mac_Instant Translate for Mac-即時翻譯Mac版下載 V1.3.0-PC6蘋果網

即時翻譯(Instant Translate)Mac版是一款Mac平臺的翻譯及辭典軟件&#xff0c;Instant Translate支持90的語言互翻譯&#xff0c;通過ControlS切換語言&#xff0c;并且支持發音功能&#xff0c;并且支持自動檢測語言并進行翻譯。軟件特色Instant Translate的主要特點&#xff…

基于Zookeeper使用ZkClient實現分布式鎖

有段時間沒寫博客了&#xff0c;在整理之前寫過的一套自定義框架&#xff0c;并且整理好上傳值github上了&#xff0c;也有一些新功能還在開發&#xff0c;歡迎大家使用&#xff1a;一個好用的Http接口請求工具組件 可能今天這篇文章跟之前的比有些跳躍性&#xff0c;一下子就…

算法題學到的一些小語言細節

1.要學會用i&#xff1b;可以簡化很多代碼&#xff1a;i&#xff1b;copyFromMe(i)&#xff1b;可以寫成&#xff1a;copyFromeMe(i) 2.StringBuffer也跟列表一樣有append函數&#xff1b; 3.if語句是分支不能進行循環&#xff0c;要寫成while才能替代循環里面的判斷 4. 這里的…

android 按鈕帶圖標 陰影_android中帶圖標的按鈕(ImageButton)怎么用

展開全部除了Android系統自帶的Button按鈕以外&#xff0c;還提供了帶圖標的按鈕ImageButton要制作帶圖標的按鈕&#xff0c;首先要在布局62616964757a686964616fe58685e5aeb931333337613163文件中定義ImageButton&#xff0c;然后通過setImageDrawable方法來設置要顯示的圖標。…

Zookeeper基礎常用操作以及ACL權限

這次將Zookeeper的一些基礎用法以及權限這塊的都補充一下在這篇博客中。 上篇博客介紹了基于ZooKeeper實現的分布式鎖&#xff0c;也介紹了一些ZooKeeper的節點類型以及監聽機制&#xff0c;今天這里就不作過多的介紹了&#xff0c;大家也可以自行的去官方文檔上看看更具體的介…

[中醫經絡學習一]足陽明胃經

人體有六臟&#xff08;心、肝、脾、肺、腎五臟&#xff0c;再加心包&#xff09;六腑&#xff08;胃、小腸、大腸、膀胱、膽、三焦&#xff09;&#xff0c;每個臟腑都聯接著一條經絡&#xff0c;一共12條經絡&#xff0c;稱“十二正經”&#xff0c;經絡的走向在四肢兩側基本…

ThreadLocal原理解析以及是否需要調用remove方法

平常的開發過程中&#xff0c;如果有個類不是線程安全的&#xff0c;比如SimpleDateFormat&#xff0c;要使這個類在并發的過程中是線程安全的&#xff0c;那么可以將變量設置位局部變量&#xff0c;不過存在的問題就是頻繁的創建對象&#xff0c;對性能和資源會有一定降低和消…

Maven基礎及概念

前言 今天就來聊聊Maven的基礎和一些比較概念性的東西&#xff0c;還有一些常用的Maven命令啥的&#xff0c;主要是某人腦子記不住&#xff0c;記在博客中讓她自己看吧&#xff0c;省的費心給她找。 后續的文章會聊到Maven的一些比較高級用法&#xff0c;像自定義插件&#x…

織夢縮略圖自動補齊絕對路徑_織夢生成文章內容縮略圖時自動加上域名絕對路徑...

今天又接了個織夢CMS的有償服務,客戶想要后臺添加文章內容的時候,縮略圖自動變成帶上絕對路徑的格式.比如我們默認的縮略圖是這樣的 /uploads/allimg/150814/123P2NB-0-lp.png 他想要的效果是這樣的 http://www.youwujun.com.cn/uploads/allimg/150814/123P2NB-0-lp.png大家懂我…

BUAA 436 孟竹的復習計劃(二維樹狀數組)

題目鏈接&#xff1a;http://acm.buaa.edu.cn/problem/436/ 題意&#xff1a;一個數列兩種操作&#xff1a;&#xff08;1&#xff09;將某個位置的數字改成另一個數字&#xff1b;&#xff08;2&#xff09;交換兩個位置的數字。每次操作之后輸出逆序數的個數。 思路&#xff…

Maven之pom.xml常用標簽解析及鏡像配置

前言 Maven僅僅是個打包工具而已&#xff0c;個人覺得沒有太大必要花費在打包工具上&#xff0c;這里就列舉一下個人覺得會常用標簽的使用就好了&#xff0c;原理啥的基本就不太會去深度了解了&#xff0c;如果以后遇到需了解Maven工作原理的工作的話&#xff0c;到時候一定分…