前言
spring
上篇咱們分享了mybatis配置解析和初始化的過程,今天咱們接着進入下個階段。在進入下個階段前,我想拋一個問題,咱們在spring裏面直接使用Mapper接口去執行sql語句,這過程當中並無Mapper的實現類,請問mybatis是怎麼爲咱們神奇的完成整個數據讀寫過程的?今天咱們就一塊兒來解密這個過程。sql
核心運做流程
編程
要解決篇頭提出的問題,咱們就得讀mybatis的Mapper編程模型這塊的源碼。mybatis
Mapper編程模型調用鏈路app
注:上圖紅色字體的調用爲調用鏈路上重點環節ide
源碼分析源碼分析
根據上面的調用鏈路,咱們先來看看平時使用原生ibatis進行開發的一個簡單場景字體
咱們今天的源碼追蹤就從sqlSession.getMapper()這句代碼開始spa
咱們在這裏調用了getMapper, 請問mapperRegistry中的mapper是在何時,哪一個位置寫入的呢?按照思路想,是否是應該在第一階段初始化配置纔對,那麼是在哪一個位置寫入的?設計
繼續跟進跟進去看看,裏面幹了什麼事兒..
截圖中的MapperProxyFactory<>是何方聖神?
由上圖咱們能夠看到MapperProxyFactory這個類其實是一個代理工廠,由它實際產生代理對象。那個代理對象mapperInterface實際就是咱們傳入的Mapper接口類對吧?再看看newInstance()方法是何時調用的?
是否是正好是在這個getMapper方法中來調用的!OK看到這裏咱們知道這個Mapper接口對象是如何產生的了。可是剛纔咱們看到源碼MapperProxyFactory中的代理是對傳入的每一個業務Mapper加強,那它是如何加強的呢?是否能進一步解決咱們篇頭提出的問題?玄機就在這個MapperProxy類中
PlainMethodInvoker對象包裝了MapperMethod對象,看來加強的內核在這個裏面了,繼續深刻揭曉答案。
是否是看到熟悉的身影了?!sqlSession原子的操做了最終就在這裏出現了。也就是當咱們經過mapper對象調用接口方法時,方法被路由到MapperProxy中,最終經過MapperMethod核心類包裝進行當前會話的原子CRUD操做。
OK,看到這裏咱們基本上能夠斷言咱們篇頭提出的問題已經回答一半了,固然要回答好這個問題,咱們還須要進一步的深刻源碼分析,裏面的封裝還有一整套設計思路和流程。咱們下篇繼續分析。最後咱們再一塊兒來看看SqlCommandType類,在上圖execute()方法中,接口方法的識別和sql命令類型的識別全靠這個類的封裝。
正由於從mappedStatement中拿到id和sqlCommandType字段的值,才使execute的執行邏輯封裝得以實現,而SqlCommandType類就明顯封裝了這個能力。
最後再概括一下mybatis的Mapper接口編程模型中這幾個核心類
MapperRegistry : mapper接口和對應的代理對象工廠的註冊中心;
MapperProxyFactory:用於生成mapper接口動態代理的實例對象;
MapperProxy:實現了InvocationHandler接口,它是加強mapper接口的實現;
MapperMethod:封裝了Mapper接口中對應方法的信息,以及對應的sql語句的信息;它是mapper接口與映射配置文件中sql語句的橋樑,MapperMethod對象不記錄任何狀態信息,因此它能夠在多個代理對象之間共享;
總結
至此mybatis的Mapper接口編程模型的源碼解析就先告一段落,後面在mybatis核心流程的第三階段中,會展開分享ibatis的sqlSession門面底層的詳細設計思路和源碼。更多mybatis源碼的內容請繼續關注!