一、靜態代理
又是一年秋招季,很多小伙伴開始去大城市打拼。來大城市第一件事就是租房,免不了和中介打交道,因為很多房東很忙,你根本找不到他。從這個場景中就可以抽象出來代理模式:
-
ISubject:被訪問者資源的抽象
-
SubjectImpl:被訪問者具體實現類(房東)
-
SubjectProxy:被訪問者的代理實現類(中介)
UML圖如下:

舉個例子來理解一下這個設計模式:
老板讓記錄一下用戶服務的響應時間,用代理模式來實現這個功能。



一切看起來都非常的美好,老板又發話了,把產品服務的響應時間也記錄一下吧。又得寫如下3個類:
-
IProductService
-
ProductServiceImpl
-
ProductServiceProxy
UserServiceProxy和ProductServiceProxy這兩個代理類的邏輯都差不多,卻還得寫2次。其實這個還好,如果老板說,把現有系統的幾十個服務的響應時間都記錄一下吧,你是不是要瘋了?這得寫多少代理類啊?
二、動態代理
黑暗總是暫時的,終究會迎來黎明,在JDK1.3之后引入了一種稱之為動態代理(Dynamic Proxy)的機制。使用該機制,我們可以為指定的接口在系統運行期間動態地生成代理對象,從而幫助我們走出最初使用靜態代理實現AOP的窘境
動態代理的實現主要由一個類和一個接口組成,即java.lang.reflect.Proxy類和java.lang.reflect.InvocationHandler接口。
讓我們用動態代理來改造一下上面記錄系統響應時間的功能。雖然要為IUserService和IProductService兩種服務提供代理對象,但因為代理對象中要添加的橫切邏輯是一樣的。所以我們只需要實現一個InvocationHandler就可以了。代碼如下

UML圖如下。恭喜你,你現在已經理解了Spring AOP是怎么回事了,就是這么簡單,今天先不展開談Spring

先簡單談談動態代理在Mybatis中是如何被大佬玩的出神入化的
三、Mybatis核心設計思路
相信用過mybatis的小伙伴都能理解下面這段代碼,通過roleMapper這個接口直接從數據庫中拿到一個對象
Role role = roleMapper.getRole(3L);
直覺告訴我,一個接口是不能運行的啊,一定有接口的實現類,可是這個實現類我自己沒寫啊,難道mybatis幫我們生成了?你猜的沒錯,mybatis利用動態代理幫我們生成了接口的實現類,這個類就是:
org.apache.ibatis.binding.MapperProxy,
我先畫一下UML圖,MapperProxy就是下圖中的SubjectProxy類

和上面的UML類圖對比一下,發現不就少了一個SubjectImpl類嗎?那應該就是SubjectProxy類把SubjectImple類要做的事情做了唄,猜對了。SubjectProxy通過SubjectImple和SubjectImple.xml之間的映射關系知道自己應該執行什么SQL。所以mybatis最核心的思路就是這么個意思,細節之類的可以看源碼,理清最主要的思路,看源碼就能把握住重點。
關於源碼相關的內容,更進一步的解釋動態代理在MyBatis中的使用,可以參考以前的一篇文章:《動態代理之投鞭斷流!看一下MyBatis的底層實現原理!》
附錄:
https://mp.weixin.qq.com/s/ToMvAD0-QyUJgg_1eFvcaA
