摘要:靜態(tài)代理在代理模式中,通常指的時(shí)靜態(tài)代理。為實(shí)際類(lèi)的接口,對(duì)應(yīng)上面圖中的,為接口的接口有一個(gè)方法需要自己實(shí)現(xiàn),我們委托代理類(lèi)實(shí)現(xiàn)的額外功能便放在該方法里。這就是動(dòng)態(tài)代理相對(duì)于靜態(tài)代理的意義。
代理模式是二十多種設(shè)計(jì)模式中的一個(gè),屬于比較常用的設(shè)計(jì)模式。本質(zhì)上就是用來(lái)委托我們生成的代理類(lèi)去完成一些額外的功能,這樣能夠達(dá)到解耦、封裝的目的。
通??梢杂迷赗PC、AOP中。比如在RPC中,當(dāng)我們調(diào)用遠(yuǎn)程方法時(shí),需要委托代理類(lèi)幫助我們?nèi)ネㄟ^(guò)網(wǎng)絡(luò)連接遠(yuǎn)程的服務(wù)提供者,幫助我們將消息編碼發(fā)送給服務(wù)端,幫我們接受服務(wù)端發(fā)來(lái)的結(jié)果。
在代理模式中,通常指的時(shí)靜態(tài)代理。
這是靜態(tài)代理的UML圖。代理的思想是:代理類(lèi)ProxySubject擁有實(shí)際類(lèi)RealSubject的相同方法doSomething(實(shí)現(xiàn)相同的一個(gè)接口),同時(shí)代理類(lèi)內(nèi)聚了實(shí)際類(lèi)(即傳入實(shí)際類(lèi)的一個(gè)引用),在代理類(lèi)的doSomething方法中,通過(guò)實(shí)際類(lèi)的引用調(diào)用實(shí)際類(lèi)的doSomething方法,并在調(diào)用前后加入需要代理實(shí)現(xiàn)的額外功能。這樣我們就可以通過(guò)調(diào)用代理類(lèi)的相同方法來(lái)達(dá)到我們的目的。
舉個(gè)例子:
interface Subject{ void doSomething(); }
class RealSubject implements Subject{ void doSomething(){ System.out.println("doSomething"); } }
class ProxySubject implements Subject{ private Subject target; public ProxySubject(Subject target){ this.target = target; } void doSomething(){ //do before System.out.println("do before"); target.doSomething();//調(diào)用realSubject的doSomething方法 //do after System.out.println("do after"); } }
class ProxyTest{ public static void main(String args[]){ //生成代理類(lèi),并將實(shí)際類(lèi)傳入 ProxySubject proxy = new ProxySubject(new RealSubject()); proxy.doSomething(); } }
以上,通過(guò)代理類(lèi)執(zhí)行實(shí)際類(lèi)相同的方法,我們可以運(yùn)行額外的功能。這里不僅會(huì)運(yùn)行實(shí)際類(lèi)doSomething方法里面的打印“doSomething”,還會(huì)在之前打印“do before",之后打印”do after",這兩個(gè)即為額外的功能。
動(dòng)態(tài)代理上面的靜態(tài)代理其實(shí)存在一個(gè)問(wèn)題,一個(gè)實(shí)際類(lèi)對(duì)應(yīng)一個(gè)代理類(lèi),而很多時(shí)候需要代理實(shí)現(xiàn)的額外功能是相同的,比如我們要在A類(lèi)的某個(gè)方法調(diào)用前打印“before”,B類(lèi)的某個(gè)方法調(diào)用前打印“before”,C類(lèi)也有這個(gè)需求,如果用靜態(tài)代理,我們需要寫(xiě)A類(lèi)的代理,B類(lèi)的代理,C類(lèi)的代理。。。這樣豈不是要累死。
java當(dāng)中的動(dòng)態(tài)代理就是為了這個(gè)解決這個(gè)問(wèn)題。其實(shí)思路也很簡(jiǎn)單,不用去管A類(lèi)、B類(lèi)、C類(lèi)還是什么其他類(lèi),統(tǒng)一用反射調(diào)用實(shí)際類(lèi)的方法。
java提供了動(dòng)態(tài)代理類(lèi)Proxy,使用其中的靜態(tài)方法Proxy.newProxyInstance(ClassLoader loader,Class>[] interfaces, InvocationHandler h)來(lái)動(dòng)態(tài)生成代理類(lèi)。interfaces為實(shí)際類(lèi)的接口,對(duì)應(yīng)上面圖中的Subject,loader為接口的Classloader,InvocationHandler接口有一個(gè)invoke方法需要自己實(shí)現(xiàn),我們委托代理類(lèi)實(shí)現(xiàn)的額外功能便放在該方法里。需要注意的是由此看出java的動(dòng)態(tài)代理需要有接口才能使用。如果不用接口實(shí)現(xiàn)動(dòng)態(tài)代理只能求助于cglib這類(lèi)字節(jié)碼增強(qiáng)框架。
下面是動(dòng)態(tài)代理的一般實(shí)現(xiàn)方法:
public class InvokeProxy implements InvocationHandler{ private Object target; public Object bind(Object target){ this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("do something before"); method.invoke(target, args); System.out.println("do something after"); return null; /* 如果反射調(diào)用的方法有返回值: Object result; result = method.invoke(target, args); return result; */ } }
同樣有接口Subject:
interface Subject{ void doSomething(); }
假設(shè)類(lèi)A實(shí)現(xiàn)了Subject接口,可以根據(jù)如下代碼生成A的代理
public class ProxyTest { public static void main(String[] args) { Subject proxyA = (Subject)new InvokeProxy().bind(new A()); proxyA.doSomething(); } }
如果還有類(lèi)B實(shí)現(xiàn)了Subject接口,我們只需更改上面的代碼即可,而不用像靜態(tài)代理那樣重復(fù)的編寫(xiě)代碼。這就是動(dòng)態(tài)代理相對(duì)于靜態(tài)代理的意義。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/65781.html
摘要:我們今天也來(lái)做一個(gè)萬(wàn)能遙控器設(shè)計(jì)模式適配器模式將一個(gè)類(lèi)的接口轉(zhuǎn)換成客戶(hù)希望的另外一個(gè)接口。今天要介紹的仍然是創(chuàng)建型設(shè)計(jì)模式的一種建造者模式。設(shè)計(jì)模式的理論知識(shí)固然重要,但 計(jì)算機(jī)程序的思維邏輯 (54) - 剖析 Collections - 設(shè)計(jì)模式 上節(jié)我們提到,類(lèi) Collections 中大概有兩類(lèi)功能,第一類(lèi)是對(duì)容器接口對(duì)象進(jìn)行操作,第二類(lèi)是返回一個(gè)容器接口對(duì)象,上節(jié)我們介紹了...
摘要:我們今天也來(lái)做一個(gè)萬(wàn)能遙控器設(shè)計(jì)模式適配器模式將一個(gè)類(lèi)的接口轉(zhuǎn)換成客戶(hù)希望的另外一個(gè)接口。今天要介紹的仍然是創(chuàng)建型設(shè)計(jì)模式的一種建造者模式。設(shè)計(jì)模式的理論知識(shí)固然重要,但 計(jì)算機(jī)程序的思維邏輯 (54) - 剖析 Collections - 設(shè)計(jì)模式 上節(jié)我們提到,類(lèi) Collections 中大概有兩類(lèi)功能,第一類(lèi)是對(duì)容器接口對(duì)象進(jìn)行操作,第二類(lèi)是返回一個(gè)容器接口對(duì)象,上節(jié)我們介紹了...
摘要:類(lèi)的適配器結(jié)構(gòu)目標(biāo)角色這就是所期待得到的接口,由于是類(lèi)適配器模式,因此目標(biāo)不可以是類(lèi)。這種類(lèi)型的設(shè)計(jì)模式屬于結(jié)構(gòu)型模式,它是作為現(xiàn)有的類(lèi)的一個(gè)包裝。和適配器模式的關(guān)系適配器模式的用意是改變所考慮對(duì)象的接口,而代理模式不能改變。 點(diǎn)擊進(jìn)入我的博客 3.1 適配器模式 適配器模式把一個(gè)類(lèi)的接口變換成客戶(hù)端所期待的另一種接口,使得原本因接口不匹配而無(wú)法在一起工作的兩個(gè)類(lèi)能夠在一起工作。 3...
摘要:又是什么其實(shí)就是一種實(shí)現(xiàn)動(dòng)態(tài)代理的技術(shù),利用了開(kāi)源包,先將代理對(duì)象類(lèi)的文件加載進(jìn)來(lái),之后通過(guò)修改其字節(jié)碼并且生成子類(lèi)。 在實(shí)際研發(fā)中,Spring是我們經(jīng)常會(huì)使用的框架,畢竟它們太火了,也因此Spring相關(guān)的知識(shí)點(diǎn)也是面試必問(wèn)點(diǎn),今天我們就大話Aop。特地在周末推文,因?yàn)樵撈恼麻喿x起來(lái)還是比較輕松詼諧的,當(dāng)然了,更主要的是周末的我也在充電學(xué)習(xí),希望有追求的朋友們也盡量不要放過(guò)周末時(shí)...
摘要:我是一個(gè)很喜歡偷懶的程序猿,一看代理的定義,哇塞,還有這么好的事情居然可以委托別人替我干活那么倒底是不是這樣呢別著急,仔細(xì)看看本文關(guān)于代理技術(shù)的介紹,最后我會(huì)專(zhuān)門(mén)回過(guò)頭來(lái)解釋這個(gè)問(wèn)題的。 代理,或者稱(chēng)為 Proxy ,簡(jiǎn)單理解就是事情我不用去做,由其他人來(lái)替我完成。在黃勇《架構(gòu)探險(xiǎn)》一書(shū)中,我覺(jué)得很有意思的一句相關(guān)介紹是這么說(shuō)的: 賺錢(qián)方面,我就是我老婆的代理;帶小孩方面,我老婆就是我...
閱讀 635·2023-04-25 21:29
閱讀 1195·2023-04-25 21:27
閱讀 1112·2021-11-25 09:43
閱讀 1175·2021-09-29 09:43
閱讀 3692·2021-09-03 10:30
閱讀 2927·2019-08-29 15:26
閱讀 2884·2019-08-29 12:52
閱讀 1814·2019-08-29 11:10