Mybatis Mapper接口如何找到實現類

1、前言

       MyBatis 是一款優秀的持久層框架,它支持定製化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。我們在使用 Mybaits 進行開發 ,通常只需要定義幾個 Mapper 接口,然後在編寫一個 xml 文件,我們在配置文件中寫好 sql , Mybatis 幫我們完成 Mapper 接口到具體實現的調用。以及將結果映射到 model bean 中。
       但是,對於 Mapper 接口,我們並沒有編寫其實現類!Mybatis是如何找到其實現類,進而完成具體的 CRUD 方法調用的呢?原理何在?

通常我們使用 Mybatis (Mybatis 單獨使用,而不是整合 spring )的主要步驟是:

  • 構建 SqlSessionFactory ( 通過 xml 配置文件 , 或者直接編寫Java代碼)
  • 從 SqlSessionFactory 中獲取 SqlSession
  • 從 SqlSession 中獲取 Mapper
  • 調用 Mapper的方法 ,例如:userMapper.selectUser(int userId);

2、Mapper 接口是怎麼找到實現類的

   2.1、Mapper 接口註冊

       諸如UserMapper之類的Mapper接口被添加到了MapperRegistry 中的一個HashMap中。並以 Mapper 接口的 Class 對象作爲 Key , 以一個攜帶Mapper接口作爲屬性的MapperProxyFactory 實例作爲value 。

   2.2、生成Mapper接口的動態代理類

      最終是通過Proxy.newProxyInstance產生了一個UserMapper的代理對象。Mybatis 爲了完成 Mapper 接口的實現,運用了代理模式。具體是使用了JDK動態代理,這個Proxy.newProxyInstance方法生成代理類的三個要素是:

  • ClassLoader —— 指定當前接口的加載器即可
  • 當前被代理的接口是什麼 —— 這裏就是 BlogMapper
  • 代理類是什麼 —— 這裏就是 MapperProxy

代理模式中,代理類(MapperProxy)中才真正的完成了方法調用的邏輯。
MapperProxy的代碼如下:

public class MapperProxy<T> implements InvocationHandler, Serializable {
        // 實現了InvocationHandler
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //代理以後,所有Mapper的方法調用時,都會調用這個invoke方法

            if (Object.class.equals(method.getDeclaringClass())) {
                try {
                    return method.invoke(this, args); 
                } catch (Throwable t) {
                    throw ExceptionUtil.unwrapThrowable(t);
                }
            }
            // 使用了緩存
            final MapperMethod mapperMethod = cachedMapperMethod(method); 
            //執行CURD
            return mapperMethod.execute(sqlSession, args); 
        }
    }

再往下一層,就是執行JDBC那一套了,獲取鏈接,執行,得到ResultSet,解析ResultSet映射成JavaBean。

3、總結

Mapper接口是如何產生動態代理對象的,Maper接口方法最終是如何執行的。總結起來主要就是這幾個點:

  • Mapper 接口在初始SqlSessionFactory 註冊的。
  • Mapper 接口註冊在了名爲 MapperRegistry 類的 HashMap中, key = Mapper class對象; value = 創建當前Mapper的工廠。
  • Mapper 註冊之後,可以從SqlSession中get
  • SqlSession.getMapper 運用了 JDK動態代理,產生了目標Mapper接口的代理對象。
  • 動態代理的 代理類是 MapperProxy ,這裏邊最終完成了增刪改查方法的調用。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章