上一篇文章分析了mapper注解關(guān)鍵類MapperAnnotationBuilder,今天來(lái)看mapper的項(xiàng)目了解析關(guān)鍵類XMLMapperBuilder。
?
基礎(chǔ)介紹
回顧下之前是在分析configuration的初始化過(guò)程,已經(jīng)進(jìn)行到了最后一步mapperElement(root.evalNode("mappers")),這個(gè)方法里有兩種解析mapper的方法,一種是解析類,一種是解析xml文件,上一篇文章在講解析類中的注解,今天說(shuō)到的就是解析xml的流程,關(guān)鍵代碼如下:

解析mapper有4種情況可以分成根據(jù)類解析和根據(jù)xml文件解析兩類,這次是后面這類,主體方法還是比較簡(jiǎn)單。
首先根據(jù)inputStream, configuration, resource或url, configuration.getSqlFragments()四個(gè)參數(shù)初始化一個(gè)XMLMapperBuilder;
然后執(zhí)行XMLMapperBuilder對(duì)象的parse方法;
初始化XMLMapperBuilder
初始化過(guò)程源碼已在上圖的右側(cè)部分,初始化XMLMapperBuilder方法的流程與加載mybatis的配置文件關(guān)鍵類XMLConfigBuilder及其相似,都是通過(guò)xml文件創(chuàng)建XPathParser對(duì)象作為XMLMapperBuilder對(duì)象的parse屬性。最后執(zhí)行parse方法去解析xml文件內(nèi)容。
實(shí)際上XMLMapperBuilder與XMLConfigBuilder都繼承BaseBuilder類,通過(guò)名字也可以看出來(lái)他們采用的是構(gòu)建者模式,在結(jié)合他們的使用流程就能夠更加理解mybatis采用構(gòu)建者模式對(duì)不同的xml解析過(guò)程。
在初始化方法中又出現(xiàn)了一個(gè)關(guān)鍵類MapperBuilderAssistant,這個(gè)在上一篇分析MapperAnnotationBuilder類是發(fā)現(xiàn)MapperAnnotationBuilder解析了所有的注解然后把解析的內(nèi)容給到MapperBuilderAssistant對(duì)象,然后通過(guò)MapperBuilderAssistant對(duì)象生成的對(duì)象具體sql的MappedStatement對(duì)象。
這里可以大膽猜測(cè)XMLMapperBuilder應(yīng)該也是一樣,解析出xml中所有信息然后給到MapperBuilderAssistant去生產(chǎn)MappedStatement對(duì)象。
XMLMapperBuilder和MapperAnnotationBuilder都是工具人,MapperBuilderAssistant才是真正生成MappedStatement對(duì)象的類。
parse方法
parse方法比較簡(jiǎn)單在上圖中也已經(jīng)把源碼貼出來(lái)了,主要分四步:驗(yàn)證重復(fù)加載、加載mapper節(jié)點(diǎn)并解析、綁定名稱空間、解決未處理的方法。
第一三步比較簡(jiǎn)單就不在詳細(xì)說(shuō)了,而第四步是也就是parse方法最后三行代碼,他的主要作用是解決在第二步解析mapper時(shí)不能處理的一些數(shù)據(jù)進(jìn)行處理,代碼比較簡(jiǎn)單不在詳細(xì)分析了,源碼如下:

configurationElement方法
可以看出來(lái)最最關(guān)鍵的方法還是parse方法的configurationElement方法,他才是真正解析mapper.xml的方法,方法源碼如下圖:

方法比較簡(jiǎn)單,就是讀取對(duì)應(yīng)節(jié)點(diǎn)的數(shù)據(jù),進(jìn)行解析,重點(diǎn)是調(diào)用的這些解析方法,可以看到一些我們平時(shí)最常見(jiàn)的比如mapper節(jié)點(diǎn)上的namespace屬性,還有常見(jiàn)的resultMap節(jié)點(diǎn)、sql節(jié)點(diǎn)等。
這里我簡(jiǎn)單點(diǎn)就只看最后一行解析具體的select|insert|update|delete節(jié)點(diǎn)的方法,因?yàn)樗麄儗?duì)應(yīng)的就是我們具體的sql了。根據(jù)上圖可以看到獲取所有的這類節(jié)點(diǎn),然后遍歷生成了一個(gè)XMLStatementBuilder的對(duì)象并執(zhí)行parseStatementNode方法。接下來(lái)來(lái)看XMLStatementBuilder類。
XMLStatementBuilder類
XMLStatementBuilder的源碼如下圖:

XMLStatementBuilder與XMLMapperBuilder一樣都是繼承BaseBuilder類,它的XNode類型屬性context對(duì)應(yīng)mapper文件中一個(gè)select、update等節(jié)點(diǎn)。初始化方法沒(méi)什么說(shuō)的,主要看parseStatementNode方法,上圖中已經(jīng)截圖一部分,剩下部分如下圖:

parseStatementNode方法并不復(fù)雜,都是在讀取context的數(shù)據(jù),主要是最后圈出來(lái)的代碼,和上一篇解析MapperAnnotationBuilder類最后調(diào)用的是同一方法。
前面猜錯(cuò)了啊,XMLMapperBuilder連工具人都算不上,XMLStatementBuilder才算生成MappedStatement的工具人。不過(guò)仔細(xì)一想也是對(duì)的,XMLMapperBuilder對(duì)應(yīng)的是一個(gè)mapper.xml文件,而要生成的MappedStatement對(duì)應(yīng)的是具體的一條CRUD語(yǔ)句,一個(gè)xml是包含多條CRUD語(yǔ)句的。
總結(jié)
一個(gè)XMLMapperBuilder對(duì)應(yīng)一個(gè)mapper.xml文件,而XMLMapperBuilder能夠從xml文件中獲取多個(gè)CRUD語(yǔ)句對(duì)應(yīng)的節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)對(duì)應(yīng)生成一個(gè)XMLStatementBuilder對(duì)象,XMLStatementBuilder解析節(jié)點(diǎn)中所有信息后與MapperAnnotationBuilder解析出注解中包含的信息一樣交給MapperBuilderAssistant去生成一個(gè)MappedStatement。
Java程序員日常學(xué)習(xí)筆記,如理解有誤歡迎各位交流討論!
