国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

設(shè)計(jì)模式 代理模式

2019-11-07 23:53:25
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

代理實(shí)現(xiàn)可以分為靜態(tài)代理和動(dòng)態(tài)代理。

靜態(tài)代理

靜態(tài)代理模式其實(shí)很常見(jiàn),比如買(mǎi)火車(chē)票這件小事:黃牛相當(dāng)于是火車(chē)站的代理,我們可以通過(guò)黃牛買(mǎi)票,但只能去火車(chē)站進(jìn)行改簽和退票。在代碼實(shí)現(xiàn)中相當(dāng)于為一個(gè)委托對(duì)象realSubject提供一個(gè)代理對(duì)象PRoxy,通過(guò)proxy可以調(diào)用realSubject的部分功能,并添加一些額外的業(yè)務(wù)處理,同時(shí)可以屏蔽realSubject中未開(kāi)放的接口。

 

1、RealSubject 是委托類(lèi),Proxy 是代理類(lèi);2、Subject 是委托類(lèi)和代理類(lèi)的接口;3、request() 是委托類(lèi)和代理類(lèi)的共同方法;

具體代碼實(shí)現(xiàn)如下:

interface Subject { void request();}class RealSubject implements Subject { public void request(){ System.out.println("RealSubject"); }}class Proxy implements Subject { private Subject subject; public Proxy(Subject subject){ this.subject = subject; } public void request(){ System.out.println("begin"); subject.request(); System.out.println("end"); }}public class ProxyTest { public static void main(String args[]) { RealSubject subject = new RealSubject(); Proxy p = new Proxy(subject); p.request(); }}

靜態(tài)代理實(shí)現(xiàn)中,一個(gè)委托類(lèi)對(duì)應(yīng)一個(gè)代理類(lèi),代理類(lèi)在編譯期間就已經(jīng)確定。

動(dòng)態(tài)代理

動(dòng)態(tài)代理中,代理類(lèi)并不是在java代碼中實(shí)現(xiàn),而是在運(yùn)行時(shí)期生成,相比靜態(tài)代理,動(dòng)態(tài)代理可以很方便的對(duì)委托類(lèi)的方法進(jìn)行統(tǒng)一處理,如添加方法調(diào)用次數(shù)、添加日志功能等等,動(dòng)態(tài)代理分為jdk動(dòng)態(tài)代理和cglib動(dòng)態(tài)代理,下面通過(guò)一個(gè)例子看看如何實(shí)現(xiàn)jdk動(dòng)態(tài)代理。

1、定義業(yè)務(wù)邏輯

public interface Service { //目標(biāo)方法 public abstract void add(); } public class UserServiceImpl implements Service { public void add() { System.out.println("This is add service"); } }

2、利用java.lang.reflect.Proxy類(lèi)和java.lang.reflect.InvocationHandler接口定義代理類(lèi)的實(shí)現(xiàn)。

class MyInvocatioHandler implements InvocationHandler { private Object target; public MyInvocatioHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("-----before-----"); Object result = method.invoke(target, args); System.out.println("-----end-----"); return result; } // 生成代理對(duì)象 public Object getProxy() { ClassLoader loader = Thread.currentThread().getContextClassLoader(); Class<?>[] interfaces = target.getClass().getInterfaces(); return Proxy.newProxyInstance(loader, interfaces, this); }}

3、使用動(dòng)態(tài)代理

public class ProxyTest { public static void main(String[] args) { Service service = new UserServiceImpl(); MyInvocatioHandler handler = new MyInvocatioHandler(service); Service serviceProxy = (Service)handler.getProxy(); serviceProxy.add(); }}

執(zhí)行結(jié)果:

-----before-----This is add service-----end-----

代理對(duì)象的生成過(guò)程由Proxy類(lèi)的newProxyInstance方法實(shí)現(xiàn),分為3個(gè)步驟:1、ProxyGenerator.generateProxyClass方法負(fù)責(zé)生成代理類(lèi)的字節(jié)碼,生成邏輯比較復(fù)雜,有興趣的同學(xué)可以繼續(xù)分析源碼 sun.misc.ProxyGenerator;

// proxyName:格式如 "com.sun.proxy.$Proxy.1";// interfaces:代理類(lèi)需要實(shí)現(xiàn)的接口數(shù)組;// accessFlags:代理類(lèi)的訪問(wèn)標(biāo)識(shí);byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);

2、native方法Proxy.defineClass0負(fù)責(zé)字節(jié)碼加載的實(shí)現(xiàn),并返回對(duì)應(yīng)的Class對(duì)象。

Class clazz = defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);

3、利用clazz.newInstance反射機(jī)制生成代理類(lèi)的對(duì)象;

反編譯代理類(lèi)為了更清楚的理解動(dòng)態(tài)代理,通過(guò)以下方式把代理類(lèi)字節(jié)碼生成class文件。

byte[] classFile = ProxyGenerator.generateProxyClass("com.sun.proxy.$Proxy.1", service.getClass().getInterfaces());FileOutputStream out = new FileOutputStream("com.sun.proxy.$Proxy.1.class");out.write(classFile);out.flush();

使用 反編譯工具 jad jad com.sun.proxy.$Proxy.1 看看代理類(lèi)如何實(shí)現(xiàn),反編譯出來(lái)的java代碼如下:

public final class $proxy1 extends Proxy implements Service { public $proxy1(InvocationHandler invocationhandler) { super(invocationhandler); } public final boolean equals(Object obj) { try { return ((Boolean)super.h.invoke(this, m1, new Object[] { obj })).booleanValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final String toString() { try { return (String)super.h.invoke(this, m2, null); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final void add() { try { super.h.invoke(this, m3, null); return; } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final int hashCode() { try { return ((Integer)super.h.invoke(this, m0, null)).intValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } private static Method m1; private static Method m2; private static Method m3; private static Method m0; static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m3 = Class.forName("zzzzzz.Service").getMethod("add", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); } catch(NoSuchMethodException nosuchmethodexception) { throw new NoSuchMethodError(nosuchmethodexception.getMessage()); } catch(ClassNotFoundException classnotfoundexception) { throw new NoClassDefFoundError(classnotfoundexception.getMessage()); } }}

從上述代碼可以發(fā)現(xiàn):1、生成的$proxy1繼承自Proxy類(lèi),并實(shí)現(xiàn)了Service接口。2、執(zhí)行代理對(duì)象的方法,其實(shí)就是執(zhí)行InvocationHandle對(duì)象的invoke方法,傳入的參數(shù)分別是當(dāng)前代理對(duì)象,當(dāng)前執(zhí)行的方法和參數(shù)。

super.h.invoke(this, m3, null);

jdk動(dòng)態(tài)代理使用的局限性通過(guò)反射類(lèi)ProxyInvocationHandler回調(diào)接口實(shí)現(xiàn)的jdk動(dòng)態(tài)代理,要求委托類(lèi)必須實(shí)現(xiàn)一個(gè)接口,但事實(shí)上并不是所有類(lèi)都有接口,對(duì)于沒(méi)有實(shí)現(xiàn)接口的類(lèi),便無(wú)法使用該方方式實(shí)現(xiàn)動(dòng)態(tài)代理。

文/占小狼(簡(jiǎn)書(shū)作者)原文鏈接:http://www.jianshu.com/p/a1d094fc6c00著作權(quán)歸作者所有,轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),并標(biāo)注“簡(jiǎn)書(shū)作者”。


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 扎兰屯市| 抚松县| 突泉县| 杂多县| 遵化市| 清苑县| 苍南县| 会昌县| 汉中市| 嘉祥县| 张北县| 望奎县| 泗洪县| 长岭县| 南部县| 土默特左旗| 沭阳县| 威海市| 华容县| 贵定县| 景泰县| 寿宁县| 永康市| 桐庐县| 秦安县| 奉节县| 罗定市| 揭西县| 绍兴市| 晴隆县| 安陆市| 特克斯县| 贵州省| 策勒县| 五大连池市| 屏边| 太保市| 南和县| 勐海县| 嘉祥县| 临清市|