Mybatis對mapper的載入流程深入講解
今天來分析Configuration初始化的最後一部分mapper的載入。
載入方法mapperElement
XMLConfigBuilder配置Configuration的parseConfiguration方法還剩最後一行解析程式碼:mapperElement(root.evalNode("mappers"));
mapperElement方法原始碼與詳解如下圖:
從原始碼可以得出一些結論:
mappers節點支援mapper和package兩種型別子節點;
package子節點只需要name一個屬性;
一個mapper子節點有且只能有url、resource、class三個屬性中其中一個,否則會丟擲異常;
mapperElement解析兩種mappers子節點,主要程式碼我分成了4個部分,接下來逐一進行深入解析。
解析包方法addMappers
首先來看解析包的方法使用的是configuration的addMappers方法,方法主要是涉及到一個MapperRegistry型別的屬性mapperRegistry,addMappers主要流程如下圖:
addMappers方法主要涉及到的是MapperRegistry這個類,這個類有兩個屬性:config、knownMappers。 在config指向的是configuration,knownMappers存放這class檔案對應的MapperProxyFactory 。 MapperProxyFactory根據名字先猜測是建立mapper代理的工廠。
介紹完關鍵類,再來看addMappers主要分4步:
呼叫mapperRegistry屬性的addMappers(String packageName)方法這個方法會呼叫另外一個addMappers;
addMappers(String packageName,Class<?> superType)方法會遍歷指定包下面所有屬於superType子類的類,上一步傳遞的是Object.class,所以這裡是遍歷所有類,然後呼叫addMapper(mapperClass)方法;
addMapper(mapperClass)方法首先需要判斷mapperClass必須是介面, 再判斷class是否已經存在,存在會報異常 。不存在則例項化一個MapperProxyFactory物件並put進knownMappers,最後根據class建立一個MapperAnnotationBuilder並呼叫parse方法。
最後是MapperAnnotationBuilder的parse方法,MapperAnnotationBuilder是解析mapper註解的,我們後面詳解。
載入package下的mapper總的流程看下來比較簡單,實際上就是 找到對應包下面所有的介面,然後根據介面建立一個MapperProxyFactory放到configuration屬性mapperRegistry的knownMappers中 。
解析單個mapper
從解析單個mapper有三種情況,但是分兩種情況,一種是有resource或者url屬性的是直接根據屬性值生成一個XMLMapperBuilder物件,然後執行parse方法,如果是由class屬性值和載入包的最後一步方法相似,呼叫mapperRegistry的addMapper方法。
XMLMapperBuilder的初始化和parse簡單介紹原始碼如下圖:
解析mapper.xml的XMLMapperBuilder和最開始解析mybatis-config.xml的XMLConfigBuilder一樣都是繼承至mybatis的BaseBuilder,並且初始化流程也差不多。
可以看出XMLMapperBuilder類是解析mapper.xml最關鍵的類,這個類比較複雜,接下來的文章再來專門講解它。
總結
mapper的注入支援兩種方式,單個mapper注入或者整個包下面注入,也可以按載入class檔案或者xml檔案分成兩種。單個mapper注入如果是根據url或者xml則是通過載入xml檔案注入,通過url獲取掃描整個包載入則是class方式進行注入。
通過xml載入是直接根據xml生成XMLMapperBuilder,然後執行parse方法。
通過class載入則是介面類生成MapperProxyFactory,放到MapperRegistry的map屬性knownMappers中,最後通過MapperAnnotationBuilder執行parse進行解析,parse也會呼叫XMLMapperBuilder的parse方法。
後面的文章我們先解讀MapperAnnotationBuilder這個類,最終再來看最重要的類XMLMapperBuilder。
從目前原始碼可以得出一些需要注意的點:
- 一個mapper子節點有且只能有url、resource、class三個屬性中其中一個,否則會丟擲異常;
- 一個mapper只能被載入一次,重複載入會丟擲異常。
到此這篇關於Mybatis對mapper的載入流程深入講解的文章就介紹到這了,更多相關Mybatis對mapper的載入流程內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!