Mybatis的接口映射原理
1、問題引入
在使用 Mybaits時 ,只需要寫一個Mapper 接口(不用寫實現(xiàn)類),并在對應(yīng)的xml 文件中寫好 sql 。然后,Mybatis就自動實現(xiàn)了具體的 CRUD 方法調(diào)用。
通常我們使用 Mybatis 的主要步驟是:
構(gòu)建 SqlSessionFactory ( 通過 xml 配置文件 , 或者直接編寫Java代碼)
從 SqlSessionFactory 中獲取sqlSession
從sqlSession 中獲取Mapper,例如BlogMapper
調(diào)用 Mapper 的方法 ,例如:blogMapper.selectBlog(int blogId)


由此可知,session.getMapper() 方法內(nèi)部產(chǎn)生了BlogMapper接口的實現(xiàn)類,因為BlogMapper是接口。
2、接口映射原理
(1)當(dāng)解析xml配置文件時,會根據(jù)<mapper namespace="....">的namespace屬性值,判斷classpath下有沒有這樣一個接口的全路徑與namespace屬性值完全相同,如果有,則建立二者之間的映射關(guān)系。
進入XMLMapperBuilder類中,找到bindMapperForNamespace。

(2)進入Configuration類,找到addMapper方法,再進入MapperRegistry類, BlogMapper接口其實是注冊在MapperRegistry類中的。
Configuration類實際上將addMapper和getMapper委派給了MapperRegistry來執(zhí)行:
addMapper方法會針對這個Mapper接口生成一個MapperProxyFactory工廠類。
getMapper方法,會通MapperProxyFactory工廠類,返回一個Mapper接口的動態(tài)代理類。


由圖可知,Mapper接口其實是放到HashMap中,其Key 為當(dāng)前Class對象,value 為一個MapperProxyFactory 實例。
(3)回過頭來看上一節(jié)的session.getMapper() 的原理。SqlSession 接口有兩個實現(xiàn)類,一個是DefaultSqlSession,另一個是SqlSessionManager。由于在初始化SqlSessionFactory時所調(diào)用的SqlSessionFactoryBuilder的build()方法里配置的是DefaultSqlSession,所以進一步進入到DefaultSession類中,看看session.getMapper()是怎么實現(xiàn)的。繼續(xù)進入getMapper方法中,發(fā)現(xiàn)是調(diào)用的mapperRegistry的getMapper方法。


綜上可知,sqlSession.getMapper(BlogMapper.class)方法先是調(diào)用了 configuration的getMapper方法,最終是調(diào)用了MapperRegistry的getMapper方法。以BlogMapper的class對象為key,找到了對應(yīng)的value,也就是mapperProxyFactory對象,然后調(diào)用這個對象的newInstance()方法。
(4)進入MapperProxyFactory中,發(fā)現(xiàn)是通過Proxy.newProxyInstance方法產(chǎn)生了一個BlogMapper的代理對象,也就是jdk的動態(tài)代理。其中三個參數(shù)分別為:
ClassLoader —— 指定當(dāng)前接口的加載器
當(dāng)前被代理的接口 —— 這里就是BlogMapper
代理類是什么 —— 這里就是MapperProxy

(5)進入代理類MapperProxy中,找到execute方法,該方法中封裝了CRUD。

總結(jié):
當(dāng)調(diào)用sqlSession.getMapper()方法時,就會創(chuàng)建一個新的動態(tài)代理對象。
首先,Mybatis會調(diào)用XMLMapperBuilder類的bindMapperForNamespace()方法,根據(jù)xml文件中的namespace中的屬性,去找Mapper接口,如果找到,就通過configuration類(然后是MapperRegistry 類)的addMapper()方法將其注冊到MapperRegistry 類的 HashMap中,key是Mapper接口的class對象,value是當(dāng)前的Mapper的代理工廠對象mapperProxyFactory,然后調(diào)用該對象的newInstance()方法去實例化對象,newInstance()里面返回的就是基于jdk的動態(tài)代理生成的Mapper接口的代理對象,在代理類MapperProxy 中完成了CRUD的調(diào)用。
————————————————
原文鏈接:https://blog.csdn.net/qq_42098875/article/details/118967624

浙公網(wǎng)安備 33010602011771號