1、背景
最近在工做之餘,把mybatis的源碼看了下,決定本身手寫個簡單版的。實現核心的功能便可。寫完以後,執行了一下,正巧在mybatis對Mapper接口的動態代理這個核心代碼這邊發現一個問題。正好再回頭看下jdk的動態代理,才發現問題所在。mybatis
2、問題
當我用SqlSession.getMapper() 方法來獲取Mapper的代理類的時候,發現這個代理對象所展現的toString()是個null。以下圖app
而debug了一下mybatis的源碼,發現是有值,而且的確是new 代理的目標對象爲MapperProxy類型spa
3、回頭看jdk動態代理
當我在排查問題的時候,無心中發現,在執行(T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);方法時,居然會拋出 mapperProxy類的invoke方法中的異常,可是這個時候程序尚未走到任何代理的方法。
回頭找了下以前學着寫的動態代理的例子,並在invoke方法裏面輸出了method。以下:debug
啓動main方法,發現打印的內容:3d
這時候才發現,在實例化代理類的時候,會調用一次invoke()方法,而且此時調用方法的method參數是Object.toString() 。看到這發現了兩點代理
4、發現並解決問題
回到本身的手寫的mybatis源碼中,天然就定位到了以下這個地方:對象
對比一下mybatis的源碼blog
正是紅框中的代碼,本身手寫的時候認爲代理的方法的聲明類都是定義的mapper接口,這邊的判斷其實沒有必要,也走不到。然而從第三點中能夠知道,在new 代理類的時候傳入的Method爲toString方法正好進了這個分支,而且調用了當前MapperProxy實例的toString方法,返回了代理類的名稱,正是以前所缺失的。把這段代碼加上就OK了接口