日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

支付宝二面:Mybatis 接口 Mapper 内的方法为啥不能重载吗?我直接懵逼了。。。

發(fā)布時(shí)間:2025/3/21 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 支付宝二面:Mybatis 接口 Mapper 内的方法为啥不能重载吗?我直接懵逼了。。。 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

動態(tài)代理的功能:通過攔截器方法回調(diào),對目標(biāo)target方法進(jìn)行增強(qiáng)。

言外之意就是為了增強(qiáng)目標(biāo)target方法。上面這句話沒錯(cuò),但也不要認(rèn)為它就是真理,殊不知,動態(tài)代理還有投鞭斷流的霸權(quán),連目標(biāo)target都不要的科幻模式。

注:本文默認(rèn)認(rèn)為,讀者對動態(tài)代理的原理是理解的,如果不明白target的含義,難以看懂本篇文章,建議先理解動態(tài)代理。

1. 自定義JDK動態(tài)代理之投鞭斷流實(shí)現(xiàn)自動映射器Mapper

首先定義一個(gè)pojo。

public?class?User?{private?Integer?id;private?String?name;private?int?age;public?User(Integer?id,?String?name,?int?age)?{this.id?=?id;this.name?=?name;this.age?=?age;}//?getter?setter }

再定義一個(gè)接口UserMapper.java。

public?interface?UserMapper?{public?User?getUserById(Integer?id); }

接下來我們看看如何使用動態(tài)代理之投鞭斷流,實(shí)現(xiàn)實(shí)例化接口并調(diào)用接口方法返回?cái)?shù)據(jù)的。

自定義一個(gè)InvocationHandler。

import?java.lang.reflect.InvocationHandler; import?java.lang.reflect.Method; import?java.lang.reflect.Proxy;public?class?MapperProxy?implements?InvocationHandler?{@SuppressWarnings("unchecked")public?<T>?T?newInstance(Class<T>?clz)?{return?(T)?Proxy.newProxyInstance(clz.getClassLoader(),?new?Class[]?{?clz?},?this);}@Overridepublic?Object?invoke(Object?proxy,?Method?method,?Object[]?args)?throws?Throwable?{if?(Object.class.equals(method.getDeclaringClass()))?{try?{//?諸如hashCode()、toString()、equals()等方法,將target指向當(dāng)前對象thisreturn?method.invoke(this,?args);}?catch?(Throwable?t)?{}}//?投鞭斷流return?new?User((Integer)?args[0],?"zhangsan",?18);} }

上面代碼中的target,在執(zhí)行Object.java內(nèi)的方法時(shí),target被指向了this,target已經(jīng)變成了傀儡、象征、占位符。在投鞭斷流式的攔截時(shí),已經(jīng)沒有了target。

寫一個(gè)測試代碼:

public?static?void?main(String[]?args)?{MapperProxy?proxy?=?new?MapperProxy();UserMapper?mapper?=?proxy.newInstance(UserMapper.class);User?user?=?mapper.getUserById(1001);System.out.println("ID:"?+?user.getId());System.out.println("Name:"?+?user.getName());System.out.println("Age:"?+?user.getAge());System.out.println(mapper.toString()); }

output:

ID:1001 Name:zhangsan Age:18 x.y.MapperProxy@6bc7c054

這便是Mybatis自動映射器Mapper的底層實(shí)現(xiàn)原理。

可能有讀者不禁要問:你怎么把代碼寫的像初學(xué)者寫的一樣?沒有結(jié)構(gòu),且缺乏美感。

必須聲明,作為一名經(jīng)驗(yàn)老道的高手,能把程序?qū)懙南癯鯇W(xué)者寫的一樣,那必定是高手中的高手。這樣可以讓初學(xué)者感覺到親切,舒服,符合自己的Style,讓他們或她們,感覺到大牛寫的代碼也不過如此,自己甚至寫的比這些大牛寫的還要好,從此自信滿滿,熱情高漲,認(rèn)為與大牛之間的差距,僅剩下三分鐘。

推薦一個(gè)艿艿寫的 6000+ Star 的 SpringBoot + SpringCloud + Dubbo 教程的倉庫:https://github.com/YunaiV/SpringBoot-Labs

推薦一個(gè)艿艿寫的 6000+ Star 的 SpringBoot + SpringCloud + Dubbo 教程的倉庫:https://github.com/YunaiV/SpringBoot-Labs

2. Mybatis自動映射器Mapper的源碼分析

首先編寫一個(gè)測試類:

public?static?void?main(String[]?args)?{SqlSession?sqlSession?=?MybatisSqlSessionFactory.openSession();try?{StudentMapper?studentMapper?=?sqlSession.getMapper(StudentMapper.class);List<Student>?students?=?studentMapper.findAllStudents();for?(Student?student?:?students)?{System.out.println(student);}}?finally?{sqlSession.close();}}

Mapper長這個(gè)樣子:

public?interface?StudentMapper?{List<Student>?findAllStudents();Student?findStudentById(Integer?id);void?insertStudent(Student?student); }

org.apache.ibatis.binding.MapperProxy.java部分源碼。

public?class?MapperProxy<T>?implements?InvocationHandler,?Serializable?{private?static?final?long?serialVersionUID?=?-6424540398559729838L;private?final?SqlSession?sqlSession;private?final?Class<T>?mapperInterface;private?final?Map<Method,?MapperMethod>?methodCache;public?MapperProxy(SqlSession?sqlSession,?Class<T>?mapperInterface,?Map<Method,?MapperMethod>?methodCache)?{this.sqlSession?=?sqlSession;this.mapperInterface?=?mapperInterface;this.methodCache?=?methodCache;}@Overridepublic?Object?invoke(Object?proxy,?Method?method,?Object[]?args)?throws?Throwable?{if?(Object.class.equals(method.getDeclaringClass()))?{try?{return?method.invoke(this,?args);}?catch?(Throwable?t)?{throw?ExceptionUtil.unwrapThrowable(t);}}//?投鞭斷流final?MapperMethod?mapperMethod?=?cachedMapperMethod(method);return?mapperMethod.execute(sqlSession,?args);}//?...

org.apache.ibatis.binding.MapperProxyFactory.java部分源碼。

public?class?MapperProxyFactory<T>?{private?final?Class<T>?mapperInterface;@SuppressWarnings("unchecked")protected?T?newInstance(MapperProxy<T>?mapperProxy)?{return?(T)?Proxy.newProxyInstance(mapperInterface.getClassLoader(),?new?Class[]?{?mapperInterface?},?mapperProxy);}

這便是Mybatis使用動態(tài)代理之投鞭斷流。

推薦一個(gè)艿艿寫的 3000+ Star 的 SpringCloud Alibaba 電商開源項(xiàng)目的倉庫:https://github.com/YunaiV/onemall

推薦一個(gè)艿艿寫的 3000+ Star 的 SpringCloud Alibaba 電商開源項(xiàng)目的倉庫:https://github.com/YunaiV/onemall

3. 接口Mapper內(nèi)的方法能重載(overLoad)嗎?(重要)

類似下面:

public?User?getUserById(Integer?id); public?User?getUserById(Integer?id,?String?name);

Answer:不能。

原因:在投鞭斷流時(shí),Mybatis使用package+Mapper+method全限名作為key,去xml內(nèi)尋找唯一sql來執(zhí)行的。類似:key=x.y.UserMapper.getUserById,那么,重載方法時(shí)將導(dǎo)致矛盾。對于Mapper接口,Mybatis禁止方法重載(overLoad)。

注:學(xué)習(xí)時(shí),是先研究的源碼,看懂了原理。寫博文時(shí),則先闡釋原理,再閱讀的源碼。順序剛好相反,希望讀者不要因此疑惑,以為我強(qiáng)大到未卜先知。

總結(jié)

以上是生活随笔為你收集整理的支付宝二面:Mybatis 接口 Mapper 内的方法为啥不能重载吗?我直接懵逼了。。。的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。