摘要:如果那個(gè)對(duì)象在的某個(gè)遠(yuǎn)端服務(wù)器上直接操作這個(gè)對(duì)象因?yàn)榫W(wǎng)絡(luò)速度原因可能比較慢那我們可以先用來代替那個(gè)對(duì)象。這種在運(yùn)行期直接通過虛擬機(jī)加入二進(jìn)制字節(jié)碼的方法是實(shí)現(xiàn)動(dòng)態(tài)代理的手段
代理的目的到底是什么呢?字面意思上就可以解釋:代理就是“代人理事”,也就是說當(dāng)實(shí)現(xiàn)某個(gè)操作的時(shí)候發(fā)現(xiàn)根本不能使用相關(guān)的對(duì)象或者使用這個(gè)對(duì)象的效果不好的時(shí)候就建立一個(gè)“代它理事”的代理對(duì)象,讓代理對(duì)象去完成任務(wù),因?yàn)槲覀冴P(guān)注的是完成任務(wù)本身,至于是誰完成了這個(gè)任務(wù)是不重要的。在這種邏輯下,只要建立的代理對(duì)象能夠?qū)崿F(xiàn)像原來那個(gè)對(duì)象一樣的方法就行,更進(jìn)一步說,我們新建的這個(gè)代理對(duì)象有足夠大的自由度,不僅可以完成原來那個(gè)對(duì)象的功能,還能完成其他我們附加上的功能。
舉兩個(gè)例子:
如果那個(gè)對(duì)象是一個(gè)是很大的圖片,需要花費(fèi)很長(zhǎng)時(shí)間才能顯示出來,那么當(dāng)這個(gè)圖片包含在文檔中時(shí),使用編輯器或?yàn)g覽器打開這個(gè)文檔,打開文檔必須很迅速,不能等待大圖片處理完成,這時(shí)需要做個(gè)圖片Proxy來代替真正的圖片。
如果那個(gè)對(duì)象在Internet的某個(gè)遠(yuǎn)端服務(wù)器上,直接操作這個(gè)對(duì)象因?yàn)榫W(wǎng)絡(luò)速度原因可能比較慢,那我們可以先用Proxy來代替那個(gè)對(duì)象。
我們來說說靜態(tài)代理和動(dòng)態(tài)代理:
靜態(tài)代理:我們的代理對(duì)象是手動(dòng)創(chuàng)建的,代理對(duì)象內(nèi)部是有一個(gè)被代理對(duì)象對(duì)應(yīng)的類的對(duì)象的,所以如果想要執(zhí)行某些被代理對(duì)象的方法時(shí)就可以使用這個(gè)新建的代理對(duì)象的同名方法去執(zhí)行,這個(gè)時(shí)候執(zhí)行的邏輯里面其實(shí)就可以用這個(gè)內(nèi)部對(duì)象的同名方法。
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(); } }
通過上面的例子我們可以看出來新建的代理對(duì)象擁有和原對(duì)象相同的接口,所以可以像操作原對(duì)象一樣地去操作代理對(duì)象,代理對(duì)象的方法還可以做出拓展,做到原對(duì)象做不了的事情。
動(dòng)態(tài)代理:通過查看靜態(tài)類型的例子,我們有了新的問題:我們其實(shí)并想要一個(gè)準(zhǔn)確的內(nèi)部對(duì)象來完成實(shí)際的動(dòng)作,我們想要的就是原對(duì)象的類結(jié)構(gòu),然后通過重寫這個(gè)類結(jié)構(gòu)中的相關(guān)方法去直接完成任務(wù),在java中,我們完全可以通過反射去解決這個(gè)問題,完全不需要再去在代理對(duì)象內(nèi)部搞一個(gè)原對(duì)象類型的對(duì)象出來。
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(); } }
動(dòng)態(tài)代理的方式其實(shí)是反射的一種體現(xiàn),為了讓最后的代理對(duì)象能夠真的去執(zhí)行被代理的對(duì)象才能完成的任務(wù),代理對(duì)象必須要得到被代理對(duì)象的類的結(jié)構(gòu),這樣就能獲取到被代理對(duì)象的方法,截獲這個(gè)方法后可以使得方法重定向到代理對(duì)象的invoke方法上執(zhí)行被重寫的代理方法。所以新建代理對(duì)象實(shí)例的時(shí)候要將被代理類的類加載器、類實(shí)現(xiàn)的接口和重寫被代理類方法的處理器對(duì)象作為參數(shù)構(gòu)造代理對(duì)象,類加載器用以在后面使用這個(gè)代理對(duì)象的時(shí)候能夠由被代理類的類加載器所加載,類的實(shí)現(xiàn)接口用以使得這個(gè)代理對(duì)象可以對(duì)外宣稱自己實(shí)現(xiàn)了這些接口,重寫方法的處理器用于真正地重寫那些需要代理的方法,這樣一來我們可以像使用被代理對(duì)象一樣去使用代理對(duì)象,實(shí)現(xiàn)了代理對(duì)象能夠真的做到“代人理事”。
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()); } }
代理模式在虛擬機(jī)中的實(shí)現(xiàn)其實(shí)也不復(fù)雜,在運(yùn)行期在字節(jié)碼的基礎(chǔ)上新創(chuàng)建一個(gè)臨時(shí)代理類,臨時(shí)代理類的各方法其實(shí)就是被代理類的同名方法的反射,執(zhí)行這些方法的時(shí)候就會(huì)執(zhí)行被代理的類中的反射出的同名方法。這種在運(yùn)行期直接通過虛擬機(jī)加入二進(jìn)制字節(jié)碼的方法是實(shí)現(xiàn)動(dòng)態(tài)代理的手段:
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 ; }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/64692.html
摘要:受知乎文章和設(shè)計(jì)模式之禪的啟發(fā),我也來搞一篇腦洞小開的文章由標(biāo)題可知,這篇文章是寫給我女朋友看的。于是這就讓經(jīng)紀(jì)人對(duì)粉絲說只有萬,我才會(huì)寫代碼。 前言 只有光頭才能變強(qiáng) 回顧前面: ThreadLocal就是這么簡(jiǎn)單 多線程三分鐘就可以入個(gè)門了! 多線程基礎(chǔ)必要知識(shí)點(diǎn)!看了學(xué)習(xí)多線程事半功倍 Java鎖機(jī)制了解一下 AQS簡(jiǎn)簡(jiǎn)單單過一遍 Lock鎖子類了解一下 線程池你真不來了解一下...
Java的三種代理模式 參考:http://www.cnblogs.com/cenyu/...Java核心技術(shù)原書第九版6.5節(jié) 為什么使用代理 我們?cè)趯懸粋€(gè)功能函數(shù)時(shí),經(jīng)常需要在其中寫入與功能不是直接相關(guān)但很有必要的代 碼,如日志記錄,信息發(fā)送,安全和事務(wù)支持等,這些枝節(jié)性代碼雖然是必要的,但它會(huì)帶來以下麻煩: 枝節(jié)性代碼游離在功能性代碼之外,它不是函數(shù)的目的,這是對(duì)OO是一種破壞 枝節(jié)性...
摘要:中的詳解必修個(gè)多線程問題總結(jié)個(gè)多線程問題總結(jié)有哪些源代碼看了后讓你收獲很多,代碼思維和能力有較大的提升有哪些源代碼看了后讓你收獲很多,代碼思維和能力有較大的提升開源的運(yùn)行原理從虛擬機(jī)工作流程看運(yùn)行原理。 自己實(shí)現(xiàn)集合框架 (三): 單鏈表的實(shí)現(xiàn) 自己實(shí)現(xiàn)集合框架 (三): 單鏈表的實(shí)現(xiàn) 基于 POI 封裝 ExcelUtil 精簡(jiǎn)的 Excel 導(dǎo)入導(dǎo)出 由于 poi 本身只是針對(duì)于 ...
摘要:設(shè)計(jì)模式之代理模式今天學(xué)到的動(dòng)態(tài)代理實(shí)現(xiàn),對(duì)代理這個(gè)概念很模糊,看了一篇文章發(fā)現(xiàn)這是一種設(shè)計(jì)模式,于是學(xué)習(xí)記錄一下。簡(jiǎn)介代理模式是一種對(duì)象結(jié)構(gòu)型的模式,主要為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問。下面依次講解著三種代理。 設(shè)計(jì)模式之代理模式 今天學(xué)到Spring的動(dòng)態(tài)代理實(shí)現(xiàn)AOP,對(duì)代理這個(gè)概念很模糊,看了一篇文章發(fā)現(xiàn)這是一種設(shè)計(jì)模式,于是學(xué)習(xí)記錄一下。 簡(jiǎn)介 代理模式是一種對(duì)...
摘要:結(jié)構(gòu)型模式適配器模式橋接模式裝飾模式組合模式外觀模式享元模式代理模式。行為型模式模版方法模式命令模式迭代器模式觀察者模式中介者模式備忘錄模式解釋器模式模式狀態(tài)模式策略模式職責(zé)鏈模式責(zé)任鏈模式訪問者模式。 主要版本 更新時(shí)間 備注 v1.0 2015-08-01 首次發(fā)布 v1.1 2018-03-12 增加新技術(shù)知識(shí)、完善知識(shí)體系 v2.0 2019-02-19 結(jié)構(gòu)...
閱讀 775·2019-08-29 16:32
閱讀 843·2019-08-29 12:31
閱讀 3226·2019-08-26 18:26
閱讀 3165·2019-08-26 12:20
閱讀 1742·2019-08-26 12:00
閱讀 3013·2019-08-26 10:58
閱讀 2820·2019-08-23 17:08
閱讀 2315·2019-08-23 16:32