上一篇文章分析了mapper注解關鍵類MapperAnnotationBuilder,今天來看mapper的項目了解析關鍵類XMLMapperBuilder。
基礎介紹
回顧下之前是在分析configuration的初始化過程,已經進行到了最后一步mapperElement(root.evalNode("mappers")),這個方法里有兩種解析mapper的方法,一種是解析類,一種是解析xml文件,上一篇文章在講解析類中的注解,今天說到的就是解析xml的流程,關鍵代碼如下:
解析mapper有4種情況可以分成根據類解析和根據xml文件解析兩類,這次是后面這類,主體方法還是比較簡單。
首先根據inputStream, configuration, resource或url, configuration.getSqlFragments()四個參數初始化一個XMLMapperBuilder;
然后執行XMLMapperBuilder對象的parse方法;
初始化XMLMapperBuilder
初始化過程源碼已在上圖的右側部分,初始化XMLMapperBuilder方法的流程與加載mybatis的配置文件關鍵類XMLConfigBuilder及其相似,都是通過xml文件創建XPathParser對象作為XMLMapperBuilder對象的parse屬性。最后執行parse方法去解析xml文件內容。
實際上XMLMapperBuilder與XMLConfigBuilder都繼承BaseBuilder類,通過名字也可以看出來他們采用的是構建者模式,在結合他們的使用流程就能夠更加理解mybatis采用構建者模式對不同的xml解析過程。
在初始化方法中又出現了一個關鍵類MapperBuilderAssistant,這個在上一篇分析MapperAnnotationBuilder類是發現MapperAnnotationBuilder解析了所有的注解然后把解析的內容給到MapperBuilderAssistant對象,然后通過MapperBuilderAssistant對象生成的對象具體sql的MappedStatement對象。
這里可以大膽猜測XMLMapperBuilder應該也是一樣,解析出xml中所有信息然后給到MapperBuilderAssistant去生產MappedStatement對象。
XMLMapperBuilder和MapperAnnotationBuilder都是工具人,MapperBuilderAssistant才是真正生成MappedStatement對象的類。
parse方法
parse方法比較簡單在上圖中也已經把源碼貼出來了,主要分四步:驗證重復加載、加載mapper節點并解析、綁定名稱空間、解決未處理的方法。
第一三步比較簡單就不在詳細說了,而第四步是也就是parse方法最后三行代碼,他的主要作用是解決在第二步解析mapper時不能處理的一些數據進行處理,代碼比較簡單不在詳細分析了,源碼如下:
configurationElement方法
可以看出來最最關鍵的方法還是parse方法的configurationElement方法,他才是真正解析mapper.xml的方法,方法源碼如下圖:
方法比較簡單,就是讀取對應節點的數據,進行解析,重點是調用的這些解析方法,可以看到一些我們平時最常見的比如mapper節點上的namespace屬性,還有常見的resultMap節點、sql節點等。
這里我簡單點就只看最后一行解析具體的select|insert|update|delete節點的方法,因為他們對應的就是我們具體的sql了。根據上圖可以看到獲取所有的這類節點,然后遍歷生成了一個XMLStatementBuilder的對象并執行parseStatementNode方法。接下來來看XMLStatementBuilder類。
XMLStatementBuilder類
XMLStatementBuilder的源碼如下圖:
XMLStatementBuilder與XMLMapperBuilder一樣都是繼承BaseBuilder類,它的XNode類型屬性context對應mapper文件中一個select、update等節點。初始化方法沒什么說的,主要看parseStatementNode方法,上圖中已經截圖一部分,剩下部分如下圖:
parseStatementNode方法并不復雜,都是在讀取context的數據,主要是最后圈出來的代碼,和上一篇解析MapperAnnotationBuilder類最后調用的是同一方法。
前面猜錯了啊,XMLMapperBuilder連工具人都算不上,XMLStatementBuilder才算生成MappedStatement的工具人。不過仔細一想也是對的,XMLMapperBuilder對應的是一個mapper.xml文件,而要生成的MappedStatement對應的是具體的一條CRUD語句,一個xml是包含多條CRUD語句的。
總結
一個XMLMapperBuilder對應一個mapper.xml文件,而XMLMapperBuilder能夠從xml文件中獲取多個CRUD語句對應的節點,每個節點對應生成一個XMLStatementBuilder對象,XMLStatementBuilder解析節點中所有信息后與MapperAnnotationBuilder解析出注解中包含的信息一樣交給MapperBuilderAssistant去生成一個MappedStatement。
Java程序員日常學習筆記,如理解有誤歡迎各位交流討論!