代理模式
解說:給某一個對象提供一個代理,并由代理對象控制對原對象的引用;
代理模式需要以下幾個角色:
1 ?主題:規(guī)定代理類和真實對象共同對外暴露的接口;
2 ?代理類:專門代理真實對象的類;
3 ?真實對象:需要被代理的對象;
代理解決的主要的業(yè)務就是需要在 真實對象的某個接口 前后處理一些事情,框架中多會用到這種功能,比如 打日志、記錄時間等
靜態(tài)代理
靜態(tài)代理是指自己動手編寫代碼實現(xiàn)代理類;
優(yōu)點:業(yè)務類只需要關注業(yè)務邏輯本身,保證了業(yè)務類的重用性。這是代理的共有優(yōu)點。
缺點:每一個真實對象都需要一個具體的代理類,不能做到可重用;
靜態(tài)代理比較簡單,下邊用代碼來具體說明;
主題接口:IAnimal

真實對象:Dog

代理:DogProxy

靜態(tài)代理使用:

代理和真實對象對外暴露一致
動態(tài)代理
動態(tài)代理是指在運行時動態(tài)生成代理類;
jdk
要使用Java中原生的動態(tài)代理,需要用到以下幾個類和接口
接口InvocationHandler
Proxy類
我們還是用靜態(tài)代理用到的代碼:主題接口IAnimal和真實對象Dog不變,去掉DogProxy和StaticProxyTest,增加以下代碼
DogProxyInvocationHandler

DynamicProxyTest

可以看出:Java動態(tài)代理 我們必須有真實對象,實現(xiàn)了InvocationHandler接口的自己的處理類,然后通過Proxy生成代理類
輸出如下:

這里動態(tài)代理的優(yōu)勢相比靜態(tài)代理為:即使真實對象有N個接口,我們的invocationHandler只需要一個Invoke方法即可!
這里有幾個問題:
1 ?動態(tài)代理生成的class name為什么是 $Proxy0 ?

相關變量如下:


以上便可以解決相關問題
2 ?動態(tài)代理生成的代理類到底是什么樣子的?生成代理類的關鍵接口是什么?為何調用真實對象的某個接口會進入invoke方法?
通過分析源碼:我們知道 Proxy.newProxyInstance?→ Proxy.getProxyClass0?→ WeakCache.get?→ WeakCache.Factory.get?→ Proxy.ProxyClassFactory.apply?→ ProxyGenerator.generateProxyClass
最終生成了一個 byte[] 類型的 class類;這樣byte[] 比較抽象 ,我們想看到該怎么辦?可以通過下邊的代碼生成Proxy0

生成的代碼如下

以上代碼為我們解答了紅色的問題。雖然代碼是這樣的? 代理類集成了 Proxy類,但是如果想要驗證 如何驗證呢?
cglib
cglib是什么?CGLIB is a powerful, high performance code generation library.
特點簡單說:
CGLib (Code Generation Library) 是一個強大的,高性能,高質量的Code生成類庫;
它可以在運行期擴展Java類與實現(xiàn)Java接口;
CGLib 比 Java 的 java.lang.reflect.Proxy 類更強的在于它不僅可以接管接口類的方法,還可以接管普通類的方法。
CGLib 的底層是Java字節(jié)碼操作框架 —— ASM
引入JAR包支持,如下:

目前最新的版本是 3.2.4,CGLib的package分布和作用如下:
net.sf.cglib.core:底層字節(jié)碼處理類,他們大部分與ASM有關系,對其進行封裝,更易于使用;
net.sf.cglib.transform:編譯期或運行期類和類文件的轉換;
net.sf.cglib.proxy:實現(xiàn)創(chuàng)建代理和方法攔截器的類;
net.sf.cglib.reflect:實現(xiàn)快速反射的類;
net.sf.cglib.util:集合排序工具類;
net.sf.cglib.beans:JavaBean相關的工具類;
我們沿用上邊的例子,來做下演示:
加入你有一個類Animal,打算對里邊的所有方法進行包裝,由于這個類沒有實現(xiàn)接口,所以你無法使用jdk 動態(tài)代理

你現(xiàn)在想要在testt方法輸出前后不加任何內容,但是另外兩個方法輸出前后要加一個字符串,效果如下:

其中=======是分隔線,上邊兩個方法前后都改變了,但是最后一個方法則沒做任何改變還是原生的。如何做到?
首先我們要定義一個攔截器,該攔截器實現(xiàn)了 cgLib的MethodInterceptor,如下:

再定義一個攔截器過濾器,如下:

接下來看下測試類:

CGLib通過 Enhancer、Callback、CallbackFilter就可以實現(xiàn)上述功能了。
深入代碼:Enhancer?→ KeyFactory.Generator?→ AbstractClassGenerator?→ DefaultGeneratorStrategy.generate?→ KeyFactory.Generator.generateClass?→ ClassWriter.toByteArray 生成 class bytecode .
生成的代碼反編譯如下:

附博客:動態(tài)代理