摘要:如果那個對象在的某個遠端服務器上直接操作這個對象因為網絡速度原因可能比較慢那我們可以先用來代替那個對象。這種在運行期直接通過虛擬機加入二進制字節碼的方法是實現動態代理的手段
代理的目的到底是什么呢?字面意思上就可以解釋:代理就是“代人理事”,也就是說當實現某個操作的時候發現根本不能使用相關的對象或者使用這個對象的效果不好的時候就建立一個“代它理事”的代理對象,讓代理對象去完成任務,因為我們關注的是完成任務本身,至于是誰完成了這個任務是不重要的。在這種邏輯下,只要建立的代理對象能夠實現像原來那個對象一樣的方法就行,更進一步說,我們新建的這個代理對象有足夠大的自由度,不僅可以完成原來那個對象的功能,還能完成其他我們附加上的功能。
舉兩個例子:
如果那個對象是一個是很大的圖片,需要花費很長時間才能顯示出來,那么當這個圖片包含在文檔中時,使用編輯器或瀏覽器打開這個文檔,打開文檔必須很迅速,不能等待大圖片處理完成,這時需要做個圖片Proxy來代替真正的圖片。
如果那個對象在Internet的某個遠端服務器上,直接操作這個對象因為網絡速度原因可能比較慢,那我們可以先用Proxy來代替那個對象。
我們來說說靜態代理和動態代理:
靜態代理:我們的代理對象是手動創建的,代理對象內部是有一個被代理對象對應的類的對象的,所以如果想要執行某些被代理對象的方法時就可以使用這個新建的代理對象的同名方法去執行,這個時候執行的邏輯里面其實就可以用這個內部對象的同名方法。
interface Subject{ public void operate(); } class SubjectImpl implements Subject{ @Override public void operate() { System. out.println( "real operate"); } } class SubjProxy implements Subject{ SubjectImpl subjectImpl = new SubjectImpl(); @Override public void operate() { System. out.println( "proxy starts"); subjectImpl.operate(); } } public class TestClass { public static void main(String[] args) { SubjProxy proxy = new SubjProxy(); proxy.operate(); } }
通過上面的例子我們可以看出來新建的代理對象擁有和原對象相同的接口,所以可以像操作原對象一樣地去操作代理對象,代理對象的方法還可以做出拓展,做到原對象做不了的事情。
動態代理:通過查看靜態類型的例子,我們有了新的問題:我們其實并想要一個準確的內部對象來完成實際的動作,我們想要的就是原對象的類結構,然后通過重寫這個類結構中的相關方法去直接完成任務,在java中,我們完全可以通過反射去解決這個問題,完全不需要再去在代理對象內部搞一個原對象類型的對象出來。
interface Subject{ public void operate(); } class SubjectImpl implements Subject{ @Override public void operate() { System. out.println( "real operate"); } } public class TestClass { public static void main(String[] args) { Subject subject = (Subject)Proxy.newProxyInstance(SubjectImpl. class.getClassLoader(), SubjectImpl.class.getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System. out.println( "Proxy operate"); return null; } }); subject.operate(); } }
動態代理的方式其實是反射的一種體現,為了讓最后的代理對象能夠真的去執行被代理的對象才能完成的任務,代理對象必須要得到被代理對象的類的結構,這樣就能獲取到被代理對象的方法,截獲這個方法后可以使得方法重定向到代理對象的invoke方法上執行被重寫的代理方法。所以新建代理對象實例的時候要將被代理類的類加載器、類實現的接口和重寫被代理類方法的處理器對象作為參數構造代理對象,類加載器用以在后面使用這個代理對象的時候能夠由被代理類的類加載器所加載,類的實現接口用以使得這個代理對象可以對外宣稱自己實現了這些接口,重寫方法的處理器用于真正地重寫那些需要代理的方法,這樣一來我們可以像使用被代理對象一樣去使用代理對象,實現了代理對象能夠真的做到“代人理事”。
interface Subject{ public void operate(); public int func(); } class SubjectImpl implements Subject{ @Override public void operate() { System. out.println( "real operate"); } @Override public int func() { System. out.println( "func"); return 2; } } public class TestClass { public static void main(String[] args) { Subject subject = (Subject)Proxy.newProxyInstance(SubjectImpl. class.getClassLoader(), SubjectImpl.class.getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(method.getName().equals( "operate")) System. out.println( "Proxy operate"); else { System. out.println( "func"); return new Integer(1); } return null; } }); subject.operate(); System. out.println(subject.func()); } }
代理模式在虛擬機中的實現其實也不復雜,在運行期在字節碼的基礎上新創建一個臨時代理類,臨時代理類的各方法其實就是被代理類的同名方法的反射,執行這些方法的時候就會執行被代理的類中的反射出的同名方法。這種在運行期直接通過虛擬機加入二進制字節碼的方法是實現動態代理的手段:
public final class $Proxy0 extends java.lang.reflect.Proxy implements Subject{ public $Proxy0(java.lang.reflect.InvocationHandler) throws ; public final int func() throws ; public final boolean equals(java.lang.Object) throws ; public final int hashCode() throws ; public final void operate() throws ; public final java.lang.String toString() throws ; static {} throws ; }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64692.html
摘要:受知乎文章和設計模式之禪的啟發,我也來搞一篇腦洞小開的文章由標題可知,這篇文章是寫給我女朋友看的。于是這就讓經紀人對粉絲說只有萬,我才會寫代碼。 前言 只有光頭才能變強 回顧前面: ThreadLocal就是這么簡單 多線程三分鐘就可以入個門了! 多線程基礎必要知識點!看了學習多線程事半功倍 Java鎖機制了解一下 AQS簡簡單單過一遍 Lock鎖子類了解一下 線程池你真不來了解一下...
Java的三種代理模式 參考:http://www.cnblogs.com/cenyu/...Java核心技術原書第九版6.5節 為什么使用代理 我們在寫一個功能函數時,經常需要在其中寫入與功能不是直接相關但很有必要的代 碼,如日志記錄,信息發送,安全和事務支持等,這些枝節性代碼雖然是必要的,但它會帶來以下麻煩: 枝節性代碼游離在功能性代碼之外,它不是函數的目的,這是對OO是一種破壞 枝節性...
摘要:設計模式之代理模式今天學到的動態代理實現,對代理這個概念很模糊,看了一篇文章發現這是一種設計模式,于是學習記錄一下。簡介代理模式是一種對象結構型的模式,主要為其他對象提供一種代理以控制對這個對象的訪問。下面依次講解著三種代理。 設計模式之代理模式 今天學到Spring的動態代理實現AOP,對代理這個概念很模糊,看了一篇文章發現這是一種設計模式,于是學習記錄一下。 簡介 代理模式是一種對...
摘要:結構型模式適配器模式橋接模式裝飾模式組合模式外觀模式享元模式代理模式。行為型模式模版方法模式命令模式迭代器模式觀察者模式中介者模式備忘錄模式解釋器模式模式狀態模式策略模式職責鏈模式責任鏈模式訪問者模式。 主要版本 更新時間 備注 v1.0 2015-08-01 首次發布 v1.1 2018-03-12 增加新技術知識、完善知識體系 v2.0 2019-02-19 結構...
閱讀 771·2019-08-29 16:32
閱讀 841·2019-08-29 12:31
閱讀 3217·2019-08-26 18:26
閱讀 3159·2019-08-26 12:20
閱讀 1737·2019-08-26 12:00
閱讀 3011·2019-08-26 10:58
閱讀 2815·2019-08-23 17:08
閱讀 2314·2019-08-23 16:32