MyBatis源碼解析——獲取SqlSessionFactory方式
MyBatis源碼解析_獲取SqlSessionFactory
我們都知道,在Mybatis中,對數(shù)據(jù)庫的增刪改查,實(shí)際上是由SqlSession來操作的,而SqlSession又是從SqlSessionFactory中得到的,那么問題來了,SqlSessonFactory是如何獲得的呢?我們一起來解讀一下Mybatis是如何加載配置文件,從而獲取SqlSessionFactory的。
首先從Resources.getResourceAsReader(path)
傳入我們mybatis全局配置文件得到一個輸入流InputStream,這里用Reader來接收。然后new一個SqlSessionFactoryBuilder對象,這是干嘛呢,這個對象里有一個build(Reader)方法,可以將我們傳入的Reader,經(jīng)過一系列的解析過程,返回給我們一個SqlSessionFactory實(shí)例,這樣我們就得到了想要的SqlSessionFactory了,估計(jì)要是這么就結(jié)束了,讀者會不會打死我呀(哈哈)。
所以我們就詳細(xì)說一下中間的解析過程。
進(jìn)入到SqlSessionFactoryBuilder.build(Reader)方法中
它會再次調(diào)用build(Reader,environment(默認(rèn)是null),Properties(默認(rèn)是null))方法,在這里,根據(jù)我們傳入的參數(shù)先new出一個XMLConfigBuilder對象,稱為parser(就是個解析器),然后parser調(diào)用它的parse()方法,parse()方法中有一個parseConfiguration(parser.evalNode("/configuration"))方法,我們知道m(xù)ybatis的全局配置文件是以configuration作為根節(jié)點(diǎn)的,而且各個子節(jié)點(diǎn)是有嚴(yán)格順序的,這里就是找到configuration根節(jié)點(diǎn),來分別解析根節(jié)點(diǎn)下的每個子節(jié)點(diǎn),然后將解析結(jié)果放在一個Configuration中。
解析節(jié)點(diǎn)是調(diào)用XpathParser.evalNode(root , expression),返回一個XNode,當(dāng)作參數(shù),放在一個**Element(XNode)方法中去處理節(jié)點(diǎn)里每一個信息。這里我們選一個mapperElement(root.evalNode("mappers"))來看看,它是如何解析mappers這個子節(jié)點(diǎn)的。
進(jìn)入到mapperElement(XNode)方法后
先去判斷傳入的節(jié)點(diǎn)是否為null,不為null則解析XNode下的每一個孩子節(jié)點(diǎn),(在mappers標(biāo)簽下,可以插入兩種子節(jié)點(diǎn),一種是package,這種做法,要求接口和xml文檔在同一個包下,另一種是mapper,mapper節(jié)點(diǎn)里有三種屬性,分別是resource,url,class,至多只能選一種)。
這里我我們來判斷子節(jié)點(diǎn)名字是否為"package",如果是,將package節(jié)點(diǎn)中的name取出,調(diào)用Configuration.addMappers(mapperPackage)方法,實(shí)際上調(diào)用MapperRegistry.addMappers(packeagename)方法,在這里,又new出了一個ResolverUtil<Class<?>>對象resolverUtil,它可以通過find()方法,找到該包下所有的所有的class或是別的文件,然后篩選出所有.class文件(不是class文件不要),如果是接口的話(不是接口不管),new出一個MapperAnnotationBuilder對象parser(實(shí)際上也是個解析器),調(diào)用parser.parse()方法,加載與接口名相同的XML文件,保存在configuration中。
如果子節(jié)點(diǎn)名字不是package
則取出"resource"、"url"、"class"等屬性,分別進(jìn)行判空,如果屬性resource中有值,先將resource所對應(yīng)的xml文件給轉(zhuǎn)成一個InputStream,再new出一個XMLMapperBuilder(inputStream,configuration,resource)對象mapperParser(這里也是個解析器),調(diào)用parse()方法,對接口里所對應(yīng)的XML文件去解析,具體解析過程和解析mybatis全局配置文件比較類似。
在解析每一個增刪改查標(biāo)簽,都會new一個mappedStatement對象statement(這里是通過它的靜態(tài)內(nèi)部類Builder來new的),相當(dāng)于一個MappedStatemet就代表了一個增刪改查的詳細(xì)信息 ,同樣MappedStatement也保存在Configuration中。
對于url中有值,過程和resource那個一樣,這里不作講述。對于mapperClass中有值,通過全類名反射,拿到對應(yīng)的接口,調(diào)用configuration.addMapper(mapperInterface)方法,具體過程和package那個一樣,也不再講述。
經(jīng)過一系列的解析,終于完成了
mappers節(jié)點(diǎn)的所有信息也都保存在Configuration中。這個時候回到SqlSessionFactoryBuilder中,將返回的Configuration對象作為參數(shù),調(diào)用它的build(configuration)方法,這里是關(guān)鍵的一步,此時根據(jù)configuration,new出了一個DefaultSqlSessionFactory對象返回給我們。
我們來看一下DefaultSqlSessionFactory這個類有啥特別的呢,它實(shí)現(xiàn)了SqlSessionFactory接口,這個接口里有很多openSession()的重載方法,原來如此,這里我們終于得到了SqlSessionFactory,也就是一個DefaultSqlSessionFactory對象,這個對象里保存著我們的Configuration,而Configuration里又保存著我們?nèi)峙渲梦募锏乃行畔?,以?*mapper.xml文件里所有信息。
如圖所示。
好啦,SqlSessionFactory獲取過程就講到這里啦,想要了解更多細(xì)節(jié)的童鞋,也可以自己去一步步debug,跟蹤源碼,了解整個過程
用MyBatis的配置文件獲取SqlSessionFactory
import java.io.IOException; import java.io.Reader; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class GetSqlSessionFactory { private static SqlSessionFactory sqlSessionFactory; static{ String rs="mybatis-config.xml"; try { Reader reader=Resources.getResourceAsReader(rs); SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder(); sqlSessionFactory=builder.build(reader); //sqlSessionFactory.getConfiguration().addMappers("com.hengtian.mapper"); } catch (IOException e) { e.printStackTrace(); } } public static SqlSessionFactory getInstance(){ return sqlSessionFactory; } }
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
- 解析Mybatis SqlSessionFactory初始化原理
- mybatis初始化SqlSessionFactory失敗的幾個原因分析
- 使用Mybatis-Plus時的SqlSessionFactory問題及處理
- Mybatis SqlSessionFactory與SqlSession詳細(xì)講解
- 詳解Mybatis核心類SqlSessionFactory的構(gòu)建
- Mybatis中自定義實(shí)例化SqlSessionFactoryBean問題
- MyBatis-plus報(bào)錯Property ‘sqlSessionFactory‘ or ‘sqlSessionTemplate‘ are required的解決方法
- 使用Mybatis時SqlSessionFactory對象總是報(bào)空指針
相關(guān)文章
Spring?Native打包本地鏡像的操作方法(無需通過Graal的maven插件buildtools)
這篇文章主要介紹了Spring?Native打包本地鏡像,無需通過Graal的maven插件buildtools,本文探索一下,如果不通過這個插件來生成鏡像,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02visual studio 2019安裝配置可編寫c/c++語言的IDE環(huán)境
這篇文章主要介紹了visual studio 2019安裝配置可編寫c/c++語言的IDE環(huán)境,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03Maven腳手架如何基于jeecg實(shí)現(xiàn)快速開發(fā)
這篇文章主要介紹了Maven腳手架如何基于jeecg實(shí)現(xiàn)快速開發(fā),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-10-10springboot帶有進(jìn)度條的上傳功能完整實(shí)例
這篇文章主要介紹了springboot帶有進(jìn)度條的上傳功能,結(jié)合完整實(shí)例形式分析了springboot帶進(jìn)度條上傳的原理、實(shí)現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下2019-11-11一篇文章了解Jackson注解@JsonFormat及失效解決辦法
這篇文章主要給大家介紹了關(guān)于如何通過一篇文章了解Jackson注解@JsonFormat及失效解決辦法的相關(guān)資料,@JsonFormat注解是一個時間格式化注解,用于格式化時間,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11Java實(shí)現(xiàn)圖片上傳至服務(wù)器功能(FTP協(xié)議)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)圖片上傳至服務(wù)器功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-06-06maven引入kabeja依賴的實(shí)現(xiàn)步驟
本文主要介紹了maven引入kabeja依賴的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-09-09