上一篇文章分析發(fā)現(xiàn)解讀mapper關(guān)鍵是兩個(gè)類MapperAnnotationBuilder和XMLMapperBuilder,今天先來(lái)看MapperAnnotationBuilder。
?
基礎(chǔ)介紹
根據(jù)MapperAnnotationBuilder和XMLMapperBuilder兩個(gè)的名字大概也可以猜出來(lái)他們的作用,MapperAnnotationBuilder應(yīng)該是來(lái)處理mapper注解的,而XMLMapperBuilder是來(lái)處理mapper.xml文件的。
接著上一篇通過(guò)掃描接口添加mapper的方法會(huì)創(chuàng)建MapperAnnotationBuilder并執(zhí)行parse方法,具體源碼如下圖:

MapperAnnotationBuilder關(guān)鍵屬性說(shuō)明:
statementAnnotationTypes:靜態(tài)屬性,存有各種sql對(duì)于在mybatis的注解;
configuration:mybatis的全局配置;
assistant:可以當(dāng)成一個(gè)工具類,用來(lái)生成MappedStatement(后面講它的作用);
type:對(duì)于的接口類型;
初始化方法比較簡(jiǎn)單不多做介紹了,接下來(lái)看parse方法;
parse方法介紹
parse方法源碼如下圖:

處理必要的驗(yàn)證外,關(guān)鍵步驟有4步:
第一個(gè)關(guān)鍵步驟是loadXmlResource方法,右側(cè)已經(jīng)把方法貼出來(lái)是,就是通過(guò)接口類找到對(duì)應(yīng)的xml文件,然后生成XMLMapperBuilder對(duì)象進(jìn)行解析,這個(gè)后面再來(lái)分析;
第二個(gè)是關(guān)鍵步驟解析二級(jí)緩存,兩個(gè)方法分別去解析接口上CacheNamespace、CacheNamespaceRef注解,解析出注解中的值后保存到assistant和configuration中,比較簡(jiǎn)單這里就不詳細(xì)說(shuō)了;
第三步是解析結(jié)果,如果方法上有Select,SelectProvider注解,但是沒(méi)有ResultMap注解,則需要通過(guò)其他信息組裝返回結(jié)果,parseResultMap方法源碼如下圖:

如果沒(méi)有指定返回值組裝過(guò)程,則是根據(jù)接口類、方法、參數(shù)拼接成一個(gè)唯一id,最后調(diào)用assistant的addResultMap方法,addResultMap方法會(huì)創(chuàng)建一個(gè)ResultMap保存到configuration的resultMaps中,具體的后面分析;
最后關(guān)鍵一步是parseStatement方法,這個(gè)方法是MapperAnnotationBuilder的關(guān)鍵方法,接下來(lái)詳細(xì)解析下。
parseStatement方法
parseStatement方法比較長(zhǎng),這里分成兩個(gè)部分,首先是第一部分的源碼如下圖:

第一部分代碼主要是獲取了方法上面Select、Update等代表一種sql的注解,在存在這些注解的情況下再繼續(xù)處理。
首先是根據(jù)方法參數(shù)、語(yǔ)言驅(qū)動(dòng)等信息生成SqlSource對(duì)象,SqlSource是XML文件或者注解方法中對(duì)應(yīng)的sql語(yǔ)句的實(shí)現(xiàn),比如把${}替換成?這種。
然后還獲取了方法上的Options注解信息,Options注解可以配置一些主鍵,是否使用緩存等信息。
然后如果sql是insert或者update語(yǔ)句則可能需要設(shè)置主鍵,這里也可以通過(guò)注解指定。
接下來(lái)看下半部分代碼,源碼如下圖;

后半部分也分成三個(gè)步驟,首先是通過(guò)Options注解中配置的信息進(jìn)行緩存等數(shù)據(jù)的初始化,然后如果是查詢類型語(yǔ)句通過(guò)ResultMap注解或者方法生成結(jié)果id。最后把所有的值放到調(diào)用assistant的addMappedStatement的方法。
addMappedStatement方法
addMappedStatement方法比較簡(jiǎn)單,主要是又有幾個(gè)關(guān)鍵類,先看源碼如下圖:

方法還是比較簡(jiǎn)單主要是根據(jù)上一步獲取的參數(shù)創(chuàng)建一個(gè)類MappedStatement.Builder,最后通過(guò)這個(gè)類生成MappedStatement并保存到了全局配置configuration中。
一個(gè)MappedStatement對(duì)應(yīng)一個(gè)sql,它包含了我們?cè)诖a中對(duì)這個(gè)sql或者說(shuō)一個(gè)mapper方法設(shè)置的所有信息,后面使用時(shí)能夠方便的執(zhí)行,MappedStatement在后面詳解。?
總結(jié)
通過(guò)分析發(fā)現(xiàn)MapperAnnotationBuilder只是一個(gè)工具人,它只是把接口和接口中方法的上的注解解析出來(lái),然后傳遞給MapperBuilderAssistant,而MapperBuilderAssistant執(zhí)行addMappedStatement方法把從注解上面獲取到的所有信息都放到了MappedStatement的對(duì)象里面,最后把MappedStatement對(duì)象放到了全局配置configuration的mappedStatements集合屬性中。
然后就是靜待使用時(shí)從mappedStatements中獲取使用了。
Java程序員日常學(xué)習(xí)筆記,如理解有誤歡迎各位交流討論!
