手写自己的MyBatis框架-MapperProxy
我們要在Configuration 中通過getMapper()方法拿到這個代理對象,必須要有一個實現了InvocationHandler 的代理類。我們來創建它:MapperProxy。
提供一個invoke()方法。
// MapperProxy.java public class MapperProxy implements InvocationHandler {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {return null;} }invoke()的實現我們先留著,先返回null。MapperProxy 已經有了,我們回到Configuration.getMapper()完成獲取代理對象的邏輯。
返回代理對象,直接使用JDK 的動態代理:第一個參數是類加載器,第二個參數是被代理類,第三個參數是代理類。
把返回結果強轉為(T):
Configuration.java public <T> T getMapper(Class<T> clazz, SqlSession sqlSession) {return (T)Proxy.newProxyInstance(this.getClass().getClassLoader(),new Class[]{clazz},new MapperProxy()); }獲取代理類的邏輯已經實現完了,我們可以在SqlSession 中通過getMapper()拿到代理對象了,也就是可以調用invoke()方法了。接下來去完成MapperProxy 的invoke()方法。
在MapperProxy 的invoke()方法里面又調用了SqlSession 的selectOne()方法。一個問題出現了:在MapperProxy 里面根本沒有SqlSession 對象?
這兩個對象的關系怎么建立起來?MapperProxy 怎么拿到一個SqlSession 對象?
很簡單,我們可通過構造函數傳入它。
先定義一個屬性,然后在MapperProxy 的構造函數里面賦值:
// MapperProxy.java private SqlSession sqlSession; public MapperProxy(SqlSession sqlSession) {this.sqlSession = sqlSession; }因為修改了代理類的構造函數,這個時候Configuration 創建代理類的方法getMapper()也要修改。
問題:Configuration 的getMapper()方法參數中也沒有SqlSession,沒辦法傳給MapperProxy 的構造函數。怎么拿到SqlSession 呢?是直接new 一個嗎?
不需要,可以在SqlSession 調用它的時候直接把自己傳進來(紅色是修改的地方):
// Configuration.java public <T> T getMapper(Class clazz, SqlSession sqlSession) {return (T)Proxy.newProxyInstance(this.getClass().getClassLoader(),new Class[]{clazz},new MapperProxy(sqlSession)); }那么SqlSession 的getMapper()方法也要修改(紅色是修改的地方):
// SqlSession.java public <T> T getMapper(Class clazz){return configuration.getMapper(clazz, this); }現在在MapperProxy 里面已經就可以拿到SqlSession 對象了,在invoke()方法里面我們會調用SqlSession 的selectOne()方法。我們繼續來完成invoke()方法。
selectOne()方法有兩個參數, statementId 和paramater,這兩個我們怎么拿到呢?
statementId 其實就是接口的全路徑+方法名,中間加一個英文的點。
paramater 可以從方法參數中拿到,這里我們只傳了一個參數,用args[0]。
它要把statementId 和參數傳給SqlSession:
// MapperProxy.java public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String mapperInterface = method.getDeclaringClass().getName();String methodName = method.getName();String statementId = mapperInterface + "." + methodName;return sqlSession.selectOne(statementId, args[0]); }?
總結
以上是生活随笔為你收集整理的手写自己的MyBatis框架-MapperProxy的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手写自己的MyBatis框架-Confi
- 下一篇: 手写自己的MyBatis框架-Execu