Mybatis【11】-- Mybatis Mapper動(dòng)態(tài)代理怎么寫饮寞?

[TOC]

1.回顧Mybatis執(zhí)行sql的流程

在之前的代碼中我們的運(yùn)行過(guò)程再梳理一下,首先我們執(zhí)行Test剖毯,調(diào)用dao接口方法

image

接口的定義:


image

調(diào)用接口的實(shí)現(xiàn)類方法:


image

最后才是調(diào)用真正的sql:


image

上面的代碼是在接口實(shí)現(xiàn)類里面自己去執(zhí)行id旺坠,查找并執(zhí)行mapper文件里面的sql,那么我們想是不是可以減少一步呢然遏?

如果我們不用自己實(shí)現(xiàn)接口贫途,只需要將接口的名字和mapper文件的namespace對(duì)應(yīng)起來(lái),將接口里面的方法名與sql語(yǔ)句標(biāo)簽的id對(duì)應(yīng)起來(lái)是不是就可以了呢待侵?

事實(shí)上丢早,mybatis提供了這樣的做法,這就是mapper動(dòng)態(tài)代理秧倾。

2.mapper動(dòng)態(tài)代理怎么寫怨酝?

首先主配置文件(Mybatis.xml),在里面配置數(shù)據(jù)庫(kù)連接信息那先,注冊(cè)需要掃描的mapper文件:

image

定義數(shù)據(jù)庫(kù)查詢的接口农猬,里面每一個(gè)接口的名字很重要,需要和mapper里面每一條sql對(duì)應(yīng)起來(lái):

image

定義mapper文件(namespace是接口的全限定類名):

image

那我們?cè)谑褂玫臅r(shí)候售淡,需要使用sqlSession.getMapper()方法斤葱,里面?zhèn)魅氲氖墙涌冢馑际峭ㄟ^(guò)接口的全限定名揖闸,也就是前面在mapper.xml文件里面配置的命名空間nameSpace,這樣一來(lái)揍堕,就是獲取到了代理類,將daomapper.xml文件關(guān)聯(lián)起來(lái)了汤纸,而每條sqlid與我們的接口方法名字對(duì)應(yīng)起來(lái))

image

我們?cè)谇懊孢€寫到過(guò)一個(gè)selectStudentMap()方法衩茸,但是里面調(diào)用的是和SelectList()一樣的sql,在接口的實(shí)現(xiàn)類里面我們自己處理了一下蹲嚣,但是現(xiàn)在使用自動(dòng)實(shí)現(xiàn)的話,底層只會(huì)調(diào)用SelectOne()或者SelectList()方法祟牲,所以這個(gè)方法會(huì)報(bào)錯(cuò)隙畜,如果接受類型是list,那么框架會(huì)自動(dòng)使用selectList()方法说贝,否則就會(huì)選擇selectOne()這個(gè)方法议惰。

在這里我們使用的是返回的是map,所以自動(dòng)選擇返回selectOne()方法乡恕,那么就會(huì)報(bào)錯(cuò)言询。如果我們需要使用自動(dòng)返回map的話俯萎,可以自己定一個(gè)map,或者返回list之后再處理运杭,這個(gè)知識(shí)點(diǎn)后面再介紹夫啊,有興趣可以訪問(wèn):mybatis的mapper返回map結(jié)果集

3.mapper動(dòng)態(tài)代理怎么做的?

打一個(gè)斷點(diǎn)在sqlSession.getMapper()方法上:

image

我們可以看到執(zhí)行下面的接口方法(接口SqlSession的方法)

<T> T getMapper(Class<T> var1);

這是一個(gè)接口辆憔,我們可以看到實(shí)現(xiàn)接口的有兩個(gè)類撇眯,一個(gè)是DefaultSqlSession,一個(gè)是SqlSessionManager,我們需要看的是DefaultSqlSession下面的接口:

 public <T> T getMapper(Class<T> type) {
    return this.configuration.getMapper(type, this);
  }

我們知道虱咧,在創(chuàng)建sqlsession的時(shí)候熊榛,confiiguration這個(gè)配置對(duì)象已經(jīng)創(chuàng)建完成。跟進(jìn)去,這是使用mapper注冊(cè)器對(duì)象的getMapper()方法腕巡,將當(dāng)前的sqlSession對(duì)象傳遞進(jìn)去:

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);
  }

我們跟進(jìn)去源碼玄坦,可以發(fā)現(xiàn)里面使用knownMappers.get(type)來(lái)獲取mapper代理工廠,這個(gè)konwnMappers是一個(gè)hashMap绘沉,這個(gè)hashMap里面已經(jīng)初始化了mapperProxyFactory對(duì)象了煎楣,獲取到工廠對(duì)象之后,再去使用sqlSession實(shí)例化:

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }

實(shí)例化的時(shí)候梆砸,使用了mapper動(dòng)態(tài)代理:

public T newInstance(SqlSession sqlSession) {
    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }
protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

從下面的debug結(jié)果中我們可以看到转质,這是動(dòng)態(tài)代理的結(jié)果,我們看到的是dao,但是動(dòng)態(tài)代理對(duì)這個(gè)dao做了增強(qiáng)帖世,實(shí)則是一個(gè)mapperProxy休蟹。

image

【作者簡(jiǎn)介】
秦懷,公眾號(hào)【秦懷雜貨店】作者日矫,技術(shù)之路不在一時(shí)赂弓,山高水長(zhǎng),縱使緩慢哪轿,馳而不息盈魁。這個(gè)世界希望一切都很快,更快窃诉,但是我希望自己能走好每一步杨耙,寫好每一篇文章,期待和你們一起交流飘痛。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末珊膜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子宣脉,更是在濱河造成了極大的恐慌车柠,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異竹祷,居然都是意外死亡谈跛,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門塑陵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)感憾,“玉大人,你說(shuō)我怎么就攤上這事猿妈〈盗猓” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵彭则,是天一觀的道長(zhǎng)鳍刷。 經(jīng)常有香客問(wèn)我,道長(zhǎng)俯抖,這世上最難降的妖魔是什么输瓜? 我笑而不...
    開(kāi)封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮芬萍,結(jié)果婚禮上尤揣,老公的妹妹穿的比我還像新娘。我一直安慰自己柬祠,他們只是感情好北戏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著漫蛔,像睡著了一般嗜愈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上莽龟,一...
    開(kāi)封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天蠕嫁,我揣著相機(jī)與錄音,去河邊找鬼毯盈。 笑死剃毒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的搂赋。 我是一名探鬼主播赘阀,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼脑奠!你這毒婦竟也來(lái)了基公?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤捺信,失蹤者是張志新(化名)和其女友劉穎酌媒,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體迄靠,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡秒咨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了掌挚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雨席。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖吠式,靈堂內(nèi)的尸體忽然破棺而出陡厘,到底是詐尸還是另有隱情,我是刑警寧澤特占,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布糙置,位于F島的核電站,受9級(jí)特大地震影響是目,放射性物質(zhì)發(fā)生泄漏谤饭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一懊纳、第九天 我趴在偏房一處隱蔽的房頂上張望揉抵。 院中可真熱鬧,春花似錦嗤疯、人聲如沸冤今。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)戏罢。三九已至,卻和暖如春阱佛,著一層夾襖步出監(jiān)牢的瞬間帖汞,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工凑术, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留翩蘸,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓淮逊,卻偏偏與公主長(zhǎng)得像催首,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子泄鹏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容