上篇博客由于長度的原因,只是用代碼展示了靜態代理到動態代理的“進化”。那么本篇博客就動態代理的實現原理做一個介紹,從而有一個更深入的理解。當然,這也已經漸漸的脫離的代理模式的內容,因為學習是一個管中窺豹的過程,了解的越深入才能了解事務的本質。
## 問題重現
動態代理呢解決了靜態代理的兩個在一定條件下不適應的問題:其一,因為代理類中需要持有一個實際類而導致的代理類和實際類的耦合度過高的問題。其二,當接口的方法過多時,代理類的重復代碼過多的問題。第一個問題是通過Proxy類的newProxyInstance方法動態的創建代理類解決的。第二個問題則是通過一個繼承了InvocationHandler接口的類的invoke方法解決的。這里有三個關鍵詞,分別是:動態、Proxy、InvocationHandler。下面我們一一解釋!
## 動態
動態是指在運行狀態下加載、探知、使用編譯期間完全未知的classes。換句話說,Java程序可以加載一個運行時才得知名稱的class,并生成其對象實體、或改變其屬性、或喚起其methods。那么放到動態代理里就是說,代理類在程序運行之前是不存在的,而是在程序運行中才創建的。即在程序運行中才有實際的代理類產生并實例話。
## InvocationHandler接口
靜態代理的第二個問題是,每個代理的方法都要加上相同內容的代碼,重復代碼太多。實現了這個接口的類,是作為代理類的一個關聯存在的。也就是說這個類是面對代理類中的所有方法的,它把代理類的功能分成了兩個部分。對方法的加強放在了這個類里,而代理類則只實現對實際類的方法調用。
這個接口中只有一個Invoke方法這個方法就是對代理類的方法的加強。它實際是對代理方法的一個攔截處理,也就是說當調用代理類中的方法時,不論哪一個都相當于調用了Invoke方法。而在Invoke方法中對代理的方法做了一個包裝加強。Invoke方法有三個參數如下:
~~~
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//代碼略
}
~~~
proxy :在其上調用方法的代理實例
method:對應于在代理實例上調用的接口方法的 Method 實例。Method 對象的聲明類將是在其中聲明方法的接口,該接口可以是代理類賴以繼承方法的代理接口的超接口。
args: 包含傳入代理實例上方法調用的參數值的對象數組,如果接口方法不使用參數,則為 null。
## Proxy類
這個類是動態的產生代理類的關鍵,先看看下表對該類的方法有些了解。這其中目前我覺得比較重要的是NewProxyInstance方法。所以這個介紹一下,其他的就查Java的api文檔吧。

~~~
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)<span style="font-family: FangSong_GB2312;">? ? ? ? ? ? ??</span>
~~~
參數:
loader - 定義代理類的類加載器
interfaces - 代理類要實現的接口列表
h - 指派方法調用的調用處理程序
返回:
一個帶有代理類的指定調用處理程序的代理實例,它由指定的類加載器定義,并實現指定的接口? ? ? ? ? ? ??
**總結**:到這里動態代理包含的內容都做了基本介紹,那么經過這幾天的學習呢其實動態代理我們只要分開兩個過程看,一個是代理的創建過程如下圖,一個是代理模式的實現,這個就不上圖了。這里需要強調的是代理模式的類圖在動態代理中具有時間性,因為沒有創建代理之前那么代理模式是不存在的。

那么這里真正新奇的東西是Proxy類中的newProxyInstance方法,幾個參數的說明都是莫名其妙的。這里涉及到java的另一知識:反射機制。而動態代理只是它的一個典型應用。那么下篇博客再見了,反射機制!