手写自己的MyBatis框架-MapperProxy
我們要在Configuration 中通過getMapper()方法拿到這個(gè)代理對(duì)象,必須要有一個(gè)實(shí)現(xiàn)了InvocationHandler 的代理類。我們來創(chuàng)建它:MapperProxy。
提供一個(gè)invoke()方法。
// MapperProxy.java public class MapperProxy implements InvocationHandler {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {return null;} }invoke()的實(shí)現(xiàn)我們先留著,先返回null。MapperProxy 已經(jīng)有了,我們回到Configuration.getMapper()完成獲取代理對(duì)象的邏輯。
返回代理對(duì)象,直接使用JDK 的動(dòng)態(tài)代理:第一個(gè)參數(shù)是類加載器,第二個(gè)參數(shù)是被代理類,第三個(gè)參數(shù)是代理類。
把返回結(jié)果強(qiáng)轉(zhuǎn)為(T):
Configuration.java public <T> T getMapper(Class<T> clazz, SqlSession sqlSession) {return (T)Proxy.newProxyInstance(this.getClass().getClassLoader(),new Class[]{clazz},new MapperProxy()); }獲取代理類的邏輯已經(jīng)實(shí)現(xiàn)完了,我們可以在SqlSession 中通過getMapper()拿到代理對(duì)象了,也就是可以調(diào)用invoke()方法了。接下來去完成MapperProxy 的invoke()方法。
在MapperProxy 的invoke()方法里面又調(diào)用了SqlSession 的selectOne()方法。一個(gè)問題出現(xiàn)了:在MapperProxy 里面根本沒有SqlSession 對(duì)象?
這兩個(gè)對(duì)象的關(guān)系怎么建立起來?MapperProxy 怎么拿到一個(gè)SqlSession 對(duì)象?
很簡(jiǎn)單,我們可通過構(gòu)造函數(shù)傳入它。
先定義一個(gè)屬性,然后在MapperProxy 的構(gòu)造函數(shù)里面賦值:
// MapperProxy.java private SqlSession sqlSession; public MapperProxy(SqlSession sqlSession) {this.sqlSession = sqlSession; }因?yàn)樾薷牧舜眍惖臉?gòu)造函數(shù),這個(gè)時(shí)候Configuration 創(chuàng)建代理類的方法getMapper()也要修改。
問題:Configuration 的getMapper()方法參數(shù)中也沒有SqlSession,沒辦法傳給MapperProxy 的構(gòu)造函數(shù)。怎么拿到SqlSession 呢?是直接new 一個(gè)嗎?
不需要,可以在SqlSession 調(diào)用它的時(shí)候直接把自己傳進(jìn)來(紅色是修改的地方):
// 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); }現(xiàn)在在MapperProxy 里面已經(jīng)就可以拿到SqlSession 對(duì)象了,在invoke()方法里面我們會(huì)調(diào)用SqlSession 的selectOne()方法。我們繼續(xù)來完成invoke()方法。
selectOne()方法有兩個(gè)參數(shù), statementId 和paramater,這兩個(gè)我們?cè)趺茨玫侥?#xff1f;
statementId 其實(shí)就是接口的全路徑+方法名,中間加一個(gè)英文的點(diǎn)。
paramater 可以從方法參數(shù)中拿到,這里我們只傳了一個(gè)參數(shù),用args[0]。
它要把statementId 和參數(shù)傳給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]); }?
總結(jié)
以上是生活随笔為你收集整理的手写自己的MyBatis框架-MapperProxy的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手写自己的MyBatis框架-Confi
- 下一篇: 手写自己的MyBatis框架-Execu