前言
? ? ? ? ?最近需要實現一個插件功能,但是如果做成兩個接口的話(即執行前和執行后),那么會降低插件的可玩性,所以需做成類似AOP的環繞通知形式,所以就使用到了責任鏈模式和代理模式進行實現。
介紹
代理模式(Proxy Pattern)
????????定義:由于某些原因需要給某對象提供一個代理以控制對該對象的訪問。這時,訪問對象不適合或者不能直接引用目標對象,代理對象作為訪問對象和目標對象之間的中介。
????????UML:
?
在Java中,常見代理模式的實現有Java靜態、動態代理,CGLIB動態代理,JAVAssist動態代理等等。
責任鏈模式(Chain of Responsibility Pattern)
?????? 定義:為請求創建了一個接收者對象的鏈。這種模式給予請求的類型,對請求的發送者和接收者進行解耦。這種類型的設計模式屬于行為型模式。
在這種模式中,通常每個接收者都包含對另一個接收者的引用。如果一個對象不能處理該請求,那么它會把相同的請求傳給下一個接收者,依此類推。
????????UML:
可以把它理解為一個鏈表,每個節點上的對象都實現了同一個接口,并且在對象內部指向下一個節點對象,在開始執行第一個節點的時候,就會傳遞到每一個節點
常見的責任鏈實現有 Servlet中的Filter,SpringMVC的Intercept攔截器,AOP中的環繞通知,Mybatis的插件功能,Druid中Filter等等。
實現
實現一個簡單的目標執行器執行
定義一個Executor接口,TargetExecutor實現Executor并實現execute方法,然后通過Executor進行調用,定義一個參數對象,模擬真實業務場景。
現在需要通過代理和責任鏈實現對Executor的execute方法進行批量增強
定義一個封裝代理對象
這個對象是用來在攔截器里面手動調用執行目標方法的,這樣就可以在攔截前和攔截后做一些業務處理等等。
?
1:proceed():當調用Proceed對象的proceed方法時,即執行代理對象的目標方法
2:targetObject: 為真實的執行對象(這個是為了記錄真實的目標執行對象,可以直接操作目標對象)
3:targetProxy: 為真實/代理對象(第一個攔截器為真實對象,后面的就是前一個攔截器的代理對象)
4:args: 目標執行對象調用方法的參數
定義一個責任鏈共用接口以及生成代理對象的共用方法
責任鏈中的共用實現接口
?
1:intercept():
?????? 每個攔截器都需要實現的方法,參數為Proceed對象,每個具體的攔截器可根據具體邏輯進行操作真實的Executor對象和ParamEvent參數對象
2:newProxy():
?????? 創建目標對象的代理方法,由于這里目標執行對象是使用接口實現的方式,所以使用的是JDK的動態代理,如果是普通的類,則可以使用CGLIB動態代理生成代理類
實現代理類的具體執行方法,進行對目標對象的增強
目標執行對象方法真實執行類,當目標執行對象調用目標執行方法時,需要調用攔截器的intercept方法,由攔截器手動調用proceed方法,進入下一個攔截器,因此形成調用鏈路。
?
1:targetObject: 具體目標執行對象
2:targetProxy:為真實/代理對象
3:intercept:下一個鏈路節點對象
4:invoke: 動態代理接口執行方法,該方法里面為調用攔截器得intercept方法
創建管理責任鏈鏈路對象
用于管理和創建目標執行對象的代理對象
?
1:interceptList:所有實現鏈路接口的對象有序集合
2:addIntercept():添加鏈路節點對象方法
3:createProxy(): 創建代理對象方法,參數為target(具體執行對象),利用循環創建代理對象將所有的攔截器生成一個責任鏈鏈路。
驗證
記錄execute方法的運行時間攔截器
修改目標執行方法的對象參數攔截器
修改目標執行對象屬性值攔截器
?
-
查看運行結果:
?
攔截器功能實現成功!