Mybatis中Mapper接口如何和xml中sql關(guān)聯(lián)(一)

在使用Mybatis開(kāi)發(fā)中思喊,或者和Spring整合中垃沦,在Dao層中的Mapper接口對(duì)xml中的sql對(duì)應(yīng)著艘儒,在service中直接調(diào)用Dao中的方法達(dá)到訪問(wèn)sql,如下:
這是一個(gè)Mapper的接口

public interface ActivityCzMapper {
    ActivityCz selectByPrimaryKey(Integer id);
}

xml中對(duì)應(yīng)的sql

...
 <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from activity_cz
    where id = #{id,jdbcType=INTEGER}
  </select>
...

ActivityCzMapper 接口并沒(méi)有實(shí)現(xiàn)類(lèi)异袄,那是如何調(diào)用的sql呢咱枉?可以在源碼中學(xué)習(xí)

在MyBatis中調(diào)用一個(gè)sql時(shí)候,sqlSession.selectList(""); 在這之前通過(guò)SqlSessionFactoryBuilder的build("MYbatis配置文件")出的sqlsession球昨。
Mybatis調(diào)用接口中方法時(shí)如下

ActivityCzMapper am = sqlSession.getMapper(ActivityCzMapper.class);
        ActivityCz activityCz = am.selectByPrimaryKey(1);

我們查看org.apache.ibatis下的session的DefaultSqlSession代碼的getMapper方法

DefaultSqlSession.class文件

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

繼續(xù)找getMapper方法尔店,在Configuration.class中

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

注意這里getMapper(type, sqlSession)方法里的type是一直傳遞的Mapper接口類(lèi),sqlSession是上面的DefaultSqlSession實(shí)例主慰。繼續(xù)跳到MapperRegistry.class中的getMapper(type,sqlSession)方法中

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

這里首先看return的東西嚣州,是一個(gè)mapperProxyFactory的 newInstance實(shí)例,那么可以猜想是利用動(dòng)態(tài)代理模式共螺,繼續(xù)看mapperProxyFactory是從哪里來(lái)的该肴,可以看到這行代碼: MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type); 通過(guò)knownMappers一個(gè)map 得到的--因?yàn)樵陬?lèi)MapperRegistry中定義了private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap()這個(gè)map,
knownMappers中g(shù)et的key是我們傳來(lái)的Mapper接口(最上面示例的ActivityCzMapper ),那說(shuō)明這個(gè)map在我們getMapper方法之前應(yīng)該add過(guò)藐不,在類(lèi)MapperRegistry下面可以看到代碼:

   public <T> void addMapper(Class<T> type) {
        if(type.isInterface()) {
            if(this.hasMapper(type)) {
                throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
            }

            boolean loadCompleted = false;

            try {
                this.knownMappers.put(type, new MapperProxyFactory(type));
                MapperAnnotationBuilder parser = new MapperAnnotationBuilder(this.config, type);
                parser.parse();
                loadCompleted = true;
            } finally {
                if(!loadCompleted) {
                    this.knownMappers.remove(type);
                }

            }
        }

    }

發(fā)現(xiàn)了add里面具體的就不看匀哄,重點(diǎn)有一句代碼this.knownMappers.put(type, new MapperProxyFactory(type));
可以理解這里的type就是我們的Mapper接口,把他當(dāng)成key雏蛮,put到map中涎嚼。

這里我們?cè)倩氐組apperRegistry.class中的getMapper(type,sqlSession)方法中,找到return mapperProxyFactory.newInstance(sqlSession)的東西

跳到MapperProxyFactory.class中挑秉,可以看到代碼

  public T newInstance(SqlSession sqlSession) {
        MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
        return this.newInstance(mapperProxy);
    }

看到這個(gè)方法里法梯,new了一個(gè)MapperProxy的構(gòu)造方法,里面有三個(gè)參數(shù)犀概,第一個(gè)sqlSession是我前面提起的DefaultSqlSession立哑,第二個(gè)mapperInterface是MapperProxyFactory.class中的定義的成員變量,就是我們傳的Mapper接口阱冶,在我們前面找到的addMapper(Class<T> type) 方法中那個(gè)knownMappers的map的value值刁憋。第三個(gè)參數(shù)是一個(gè)初始化的ConcurrentHashMap在類(lèi)中這樣定義

 private Map<Method, MapperMethod> methodCache = new ConcurrentHashMap();

是空的。
注意下這個(gè)方法中new的MapperProxy類(lèi)木蹬,這個(gè)類(lèi)
public class MapperProxy<T> implements InvocationHandler, Serializable {
...
}
他實(shí)現(xiàn)了InvocationHandler至耻,說(shuō)明利用了JDK的動(dòng)態(tài)代理若皱,把三個(gè)參數(shù)初始化的MapperProxy代理類(lèi)傳到下一個(gè)重載方法。

繼續(xù)找到當(dāng)前類(lèi)的newInstance的重載方法

protected T newInstance(MapperProxy<T> mapperProxy) {
        return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
 }

到這里就可以知道了利用jdk的動(dòng)態(tài)代理模式Proxy.newProxyInstance方法尘颓,里面的三個(gè)參數(shù)顯而易見(jiàn)走触,對(duì)于第三個(gè)參數(shù)mapperProxy就是 實(shí)現(xiàn)了InvocationHandler接口的MapperProxy類(lèi)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末疤苹,一起剝皮案震驚了整個(gè)濱河市互广,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌卧土,老刑警劉巖惫皱,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異尤莺,居然都是意外死亡旅敷,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)颤霎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)媳谁,“玉大人,你說(shuō)我怎么就攤上這事友酱∏缫簦” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵缔杉,是天一觀的道長(zhǎng)锤躁。 經(jīng)常有香客問(wèn)我,道長(zhǎng)壮吩,這世上最難降的妖魔是什么进苍? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任加缘,我火速辦了婚禮鸭叙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拣宏。我一直安慰自己沈贝,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布勋乾。 她就那樣靜靜地躺著宋下,像睡著了一般。 火紅的嫁衣襯著肌膚如雪辑莫。 梳的紋絲不亂的頭發(fā)上学歧,一...
    開(kāi)封第一講書(shū)人閱讀 51,737評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音各吨,去河邊找鬼枝笨。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的横浑。 我是一名探鬼主播剔桨,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼徙融!你這毒婦竟也來(lái)了洒缀?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤欺冀,失蹤者是張志新(化名)和其女友劉穎树绩,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體隐轩,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡葱峡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了龙助。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片砰奕。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖提鸟,靈堂內(nèi)的尸體忽然破棺而出军援,到底是詐尸還是另有隱情,我是刑警寧澤称勋,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布胸哥,位于F島的核電站,受9級(jí)特大地震影響赡鲜,放射性物質(zhì)發(fā)生泄漏空厌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一银酬、第九天 我趴在偏房一處隱蔽的房頂上張望嘲更。 院中可真熱鬧,春花似錦揩瞪、人聲如沸赋朦。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)宠哄。三九已至,卻和暖如春嗤攻,著一層夾襖步出監(jiān)牢的瞬間毛嫉,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工妇菱, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留承粤,地道東北人惊畏。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像密任,于是被迫代替她去往敵國(guó)和親颜启。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

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