淺析mybatis源碼(三)Mapper

這篇主要看下mybatis的Mapper,Mapper能夠說是mybatis的入口。這裏僅討論註解的方式。
回顧下第一篇中mybatis是如何使用的。java

sqlSession = SqlSessionFactoryUtil.getSqlSession();
productMapper = sqlSession.getMapper(ProductMapper.class);
Product product = productMapper.detail(1);

能夠看到獲取Session後(第二篇講到了,本質就是獲取到一個數據庫鏈接),獲取productMapper,ProductMapper是咱們定義的一個接口,detail是咱們定義的一個抽象方法。 接口並無實現方法,所以能夠猜測到mybatis幫咱們生成了一個實現了ProductMapper接口的類。sql

思路

那能夠試想下,讓咱們本身實現這個類,是怎樣的流程呢?
首先,getMapper有個入參是ProductMapper.class。也就是咱們有ProductMapper這個接口,接口上每一個方法中的註解上都定義了該如何執行sql。經過反射可以拿到這些sql信息生成類則可使用動態代理,由於ProductMapper是接口,咱們能夠用jdk動態代理。數據庫

mybatis生成productMapper流程

mybatis生成productMapper是分兩步的,第一步是在初始化的時候addMapper,第二步則是在使用的時候getMapper。爲何要這樣作呢,由於解析註解、生成工廠類等都是重複的工做。能夠在初始化前計算好。使用的時候拿來用就好了。mybatis

getMapper流程

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }

getMapper的流程比較簡單,就是經過Mapper在knownMappers(addMapper中會講)中取到對應的Mapper代理工廠。而後經過工廠構建Mapper代理。app

addMapper流程


能夠看到最終一共生成了三份重要數據,類型分別爲Mapper代理工廠類,ResultMap,MappedStatement類。都保存在了Map結構中。
knowMappers保存在了configuration.mapperRegistry中。鍵是Mapper.class,值是對應的Mapper代理工廠。
resultMaps保存在了configuration中。鍵是個字符串,這樣拼接的"${Mapper包路徑}.${Mapper類名}.${執行方法名}.${方法返回類型}",值是這個方法對應的結果處理配置。
mappedStatments保存在了configuration中。鍵是個字符串,這樣拼接的"${Mapper包路徑}.${Mapper類名}.${執行方法名}",值是這個方法對應的sql執行配置。
那這些數據何時使用呢?
在getMapper的時候,即可以取出來Mapper工廠來生成Mapper類。
當執行Mapper中某個方法時,即可以從MappedStatement中找到執行的sql數據,獲得結果後,能夠從ResultMap中找到定義的結果類型,將結果轉爲定義的類型

後面三篇文章會分別從這三個類出發來進行討論。代理

相關文章
相關標籤/搜索