上篇提到面向接口編程需要使用getMapper獲取代理對象辛臊,今天我們來看一下mapper代理對象是如何產生的哪怔,在此之前先回憶下面試接口編程典格。
一祖娘、Mybatis面向接口編程實踐
(一)使用xml的方式
1.定義mapper接口
Mapper接口就是一個普通的接口丽焊。
[圖片上傳失敗...(image-f682a9-1542177065563)]
2.定義****mapper映射文件
[圖片上傳失敗...(image-7f393e-1542177065563)]
3.在全局配置文件中配置mapper映射文件
上篇我們也說過掷倔,雖有多種方式觸發(fā)文件解析與接口注入眉孩,不做此步驟也能完成(搞清楚一個前提我們現(xiàn)在說的都是在mybatis面向接口編程方式下),但是我們建議通過配置映射文件的方式觸發(fā)mybatis自動掃描注入勒葱。配置方式有多種浪汪,不在贅述。我們的配置方式如下:
[圖片上傳失敗...(image-994100-1542177065563)]
4.現(xiàn)在我們測試一下
[圖片上傳失敗...(image-459231-1542177065563)]
測試結果ok凛虽。
(二)使用注解的方式死遭。
1.定義mapper接口,同時使用注解
[圖片上傳失敗...(image-70796f-1542177065563)]
2.接口注入凯旋。
上篇我們也提到過呀潭,雖然用注解不需要xml映射文件,但我們可以通過配置一個只含有namespace的映射文件觸發(fā)接口注入至非。如下:
[圖片上傳失敗...(image-cb2a30-1542177065563)]
假如我們就是配置钠署,可以在使用之前調用
sqlsession.getConfiguration().addMapper(IUser.class);
3.測試,假設沒有配置xml
[圖片上傳失敗...(image-e96573-1542177065563)]
測試ok.
二睡蟋、Mybatis面向接口編程之mapper對象的產生
[圖片上傳失敗...(image-d97754-1542177065562)]
[圖片上傳失敗...(image-cbb021-1542177065562)]
[圖片上傳失敗...(image-2ff428-1542177065562)]
mapperRegistry中getMapper踏幻,首先通過Class類型在knowMappers中獲取mapperProxyFactory.這個變量就是個hashMap,是所有注冊的mapper接口,上篇我們提到過戳杀。方法直接返mapperProxyFactory.newInstance(sqlSession).我們接著看下
[圖片上傳失敗...(image-201955-1542177065562)]
由此可以看出mybatis直接使用了jdk的動態(tài)代理產生了一個mapper接口代理對象该面。
我 們下面看一下MapperProxy,的invoke方法信卡,MapperProxy是個InvocationHandler
[圖片上傳失敗...(image-40c7b4-1542177065562)]
如果是object中的方法直接調用隔缀,比如hashCode,wait.toString..這些,我們接口中并沒有default方法傍菇。最終會調用最后兩行猾瘸。
接著看下MapperMethod對象的產生
[圖片上傳失敗...(image-d07275-1542177065562)]
他有一個緩存避免了每次都重新生成一個對象,因為這個對象的創(chuàng)建過程比較復雜丢习。
構造方法如下:
[圖片上傳失敗...(image-13faaa-1542177065562)]
SqlCommand和MethodSignature為兩個內部類牵触,先看一下SqlCommand
[圖片上傳失敗...(image-e275e2-1542177065562)]
里面如下方法是去全局配置對象查找解析的sql語句生成的類對象,id為接口全類名+方法名,for循環(huán)為遞歸調用咐低,因為接口存在繼承關系揽思,方法不一定都聲明在本類,也可能在父類见擦,父類的父類钉汗。羹令。。损痰。福侈。。卢未。肪凛。
[圖片上傳失敗...(image-4abb5b-1542177065562)]
Come on
[圖片上傳失敗...(image-d4fb92-1542177065562)]
通過剛才的satementId取判斷Configuration中成員對象mappedStatement中是否包含[圖片上傳失敗...(image-8ae882-1542177065562)]
這個對象便是所有解析的sql語句生成的類對象的map集合,為內部類尝丐,繼承了hashMap,显拜,重寫了put,get方法。key即為namespace+語句id和語句id,兩個key對應相同對象爹袁,這也是什么用mybatis的時候远荠,語句可以不寫namespace的原因。具體解析以后再分析失息。
判斷如果存在對應的sql語句譬淳,則取到相應的MappedStatement對象,這個對象包含了映射文件中定義的語句(如select)的所有信息盹兢,比如參數(shù)邻梆,返回值,具體sql,類型(增刪蓋查)绎秒。浦妄。。等等等
內部類MethodSignature定義了接口中方法的各種信息见芹。
[圖片上傳失敗...(image-97b844-1542177065562)]
至此MapperMethod對象完成創(chuàng)建剂娄。接下來調用execute方法。
[圖片上傳失敗...(image-e84502-1542177065562)]
該方法中根據語句類型玄呛,回歸原始直接調用了sqlSession中的增刪蓋查方法阅懦,根據配置和方法信息拼裝返回結果。到此一個實現(xiàn)了mapper接口的代理對象生成完成徘铝,所以你可以盡情的使用此對象調用方法啦耳胎。