摘要:動態(tài)代理的產(chǎn)生就是這樣而來的。在的方案中我們只需要這樣做可以實現(xiàn)動態(tài)代理了。委托類實際執(zhí)行類利用提供的實現(xiàn)動態(tài)代理代理環(huán)繞執(zhí)行實際的方法利用的實現(xiàn)代理動態(tài)代理,有幾個關(guān)鍵點,一個就是接口,這個方法中的方法是執(zhí)行代理時會執(zhí)行的方法。
什么是代理?
代理是一種設(shè)計模式,簡單的說就是為某個對象提供代理,以控制這個對象的訪問,在不修改原方法的情況下做方法增強,簡單的可以分為兩種:
靜態(tài)代理
動態(tài)代理
靜態(tài)代理一般情況下的代理就是有一個接口,接口中定義了一些方法需要被實現(xiàn),實現(xiàn)了那些方法的類被稱為實現(xiàn)類,但是當我們需要在調(diào)用該方法前做一些額外的操作,又不想影響原來的代碼,這時候就可以引入一個代理類,讓代理類也實現(xiàn)該接口,然后將接口的那個實現(xiàn)類作為成員變量引入代理類中,額外操作時由代理類操作,具體到該方法時則由實現(xiàn)類去操作,下面舉個例子;
public interface Calculator {
//需要代理的接口 public int add(int a,int b); //接口實現(xiàn)類,執(zhí)行真正的a+b操作 public static class CalculatorImpl implements Calculator{ @Override public int add(int a, int b) { System.out.println("doing "); return a+b; } } //靜態(tài)代理類的實現(xiàn).代碼已經(jīng)實現(xiàn)好了. public static class CalculatorProxy implements Calculator{ private Calculator calculator; public CalculatorProxy(Calculator calculator) { this.calculator=calculator; } @Override public int add(int a, int b) { //執(zhí)行一些操作 System.out.println("begin "); int result = calculator.add(a, b); System.out.println("end "); return result; } }
}
Calculator是一個計算器的接口類,定義了一個加法的接口方法,由CalculatorImpl類實現(xiàn)真正的加法操作.現(xiàn)在如果我們想對這個方法做一層靜態(tài)的代理,這兒實現(xiàn)了一個簡單的代理類實現(xiàn)了計算接口Calculator,構(gòu)造函數(shù)傳入的參數(shù)是真正的實現(xiàn)類,但是在調(diào)用這個代理類的add方法的時候我們在CalculatorImpl的實現(xiàn)方法執(zhí)行的前后分別做了一些操作。這樣的代理方式就叫做靜態(tài)代理(這個是別人的例子,只是為了更加形象的展示靜態(tài)代理,拿代碼說話)。
很明顯靜態(tài)代理的缺點,由于我們需要事先實現(xiàn)代理類,那么每個方法我都都需要去實現(xiàn)。如果我們要實現(xiàn)很多的代理類,那么工作量就太大了。動態(tài)代理的產(chǎn)生就是這樣而來的。
動態(tài)代理使用動態(tài)代理可以讓代理類在程序運行的時候生成代理類,我們只需要為一類代理寫一個具體的實現(xiàn)類就行了,所以實現(xiàn)動態(tài)代理要比靜態(tài)代理簡單許多,省了不少重復(fù)的工作。在JDK的方案中我們只需要這樣做可以實現(xiàn)動態(tài)代理了。
public class ProxyFactory implements InvocationHandler {
private Class> target; private Object real; //委托類class public ProxyFactory(Class> target){ this.target=target; } //實際執(zhí)行類bind public Object bind(Object real){ this.real=real; //利用JDK提供的Proxy實現(xiàn)動態(tài)代理 return Proxy.newProxyInstance(target.getClassLoader(),new Class[]{target},this); } @Override public Object invoke(Object o, Method method, Object[] args) throws Throwable { //代理環(huán)繞 System.out.println("begin"); //執(zhí)行實際的方法 Object invoke = method.invoke(real, args); System.out.println("end"); return invoke; } public static void main(String[] args) { Calculator proxy =(Calculator) new ProxyFactory(Calculator.class).bind(new Calculator.CalculatorImpl()); proxy.add(1,2); }
}
利用JDK的proxy實現(xiàn)代理動態(tài)代理,有幾個關(guān)鍵點,一個就是InvocationHandler接口,這個方法中的invoke方法是執(zhí)行代理時會執(zhí)行的方法。所以我們所有代理需要執(zhí)行的邏輯都會寫在這里面,invo參數(shù)里面的method可以使用java 反射調(diào)用真實的實現(xiàn)類的方法,我們在這個方法周圍做一些代理邏輯工作就可以了。上面的代碼會把Calculator接口的所有方法全部在程序運行時代理。不用我們一個個的去寫靜態(tài)代理的方法。
public final class Calcultor$ProxyCode extends Proxy implements Calculator {
private static Method m1; private static Method m4; private static Method m0; private static Method m3; private static Method m2; public Calcultor$ProxyCode(InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue(); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final int reduce(int var1, int var2) throws { try { return ((Integer)super.h.invoke(this, m4, new Object[]{Integer.valueOf(var1), Integer.valueOf(var2)})).intValue(); } catch (RuntimeException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } } public final int hashCode() throws { try { return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue(); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final int add(int var1, int var2) throws { try { return ((Integer)super.h.invoke(this, m3, new Object[]{Integer.valueOf(var1), Integer.valueOf(var2)})).intValue(); } catch (RuntimeException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } } public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { //static靜態(tài)塊加載每個方法的Method對象 m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")}); m4 = Class.forName("jdkproxy.Calculator").getMethod("reduce", new Class[]{Integer.TYPE, Integer.TYPE}); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m3 = Class.forName("jdkproxy.Calculator").getMethod("add", new Class[]{Integer.TYPE, Integer.TYPE}); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } }
}
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/67722.html
摘要:這種語法,在中被稱為動態(tài)代理。在動態(tài)代理機制中,這個角色只能是接口。動態(tài)代理就是實現(xiàn)的技術(shù)之一。 所謂動態(tài)代理,指的是語言提供的一種語法,能夠?qū)ο笾胁煌椒ǖ恼{(diào)用重定向到一個統(tǒng)一的處理函數(shù)中來。python重寫__getattr__函數(shù)能夠做到這一點,就連世界上最好的語言也提供稱為魔術(shù)方法的__call。這種語法除了能更好的實現(xiàn)動態(tài)代理外,還是RPC框架實現(xiàn)原理的一部分。 動態(tài)代理...
摘要:自定義注解不生效原因解析及解決方法背景項目中,自己基于實現(xiàn)了一套緩存注解。但是最近出現(xiàn)一種情況緩存竟然沒有生效,大量請求被擊穿到層,導(dǎo)致壓力過大。至此,問題得到解決。 自定義注解不生效原因解析及解決方法 背景: 項目中,自己基于spring AOP實現(xiàn)了一套java緩存注解。但是最近出現(xiàn)一種情況:緩存竟然沒有生效,大量請求被擊穿到db層,導(dǎo)致db壓力過大?,F(xiàn)在我們看一下具體代碼情形(代...
摘要:由于的限制,無法替換被代理類已經(jīng)被載入的字節(jié)碼,只能生成并載入一個新的子類作為代理類,被代理類的字節(jié)碼依然存在于中。區(qū)別于前兩者,是一種靜態(tài)代理的實現(xiàn),即在編譯時或者載入類時直接修改被代理類文件的字節(jié)碼,而非運行時實時生成代理。 現(xiàn)象描述 上周同事發(fā)現(xiàn)其基于mySql實現(xiàn)的分布式鎖的線上代碼存在問題,代碼簡化如下: @Controller class XService { @A...
時間:2017年09月03日星期日說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com 教學(xué)源碼:https://github.com/zccodere/s...學(xué)習(xí)源碼:https://github.com/zccodere/s... 第一章:課程介紹 1-1 面向切面 課程章節(jié) 概覽 AOP使用 AOP原理 AOP開源運用 課程實戰(zhàn) 課程總結(jié) 面向切面編程是一種...
摘要:動態(tài)代理又被稱為代理或接口代理。靜態(tài)代理在編譯時產(chǎn)生字節(jié)碼文件,可以直接使用,效率高。代理無需實現(xiàn)接口,通過生成類字節(jié)碼實現(xiàn)代理,比反射稍快,不存在性能問題,但會繼承目標對象,需要重寫方法,所以目標對象不能為類。 一、代理模式介紹 代理模式是一種設(shè)計模式,提供了對目標對象額外的訪問方式,即通過代理對象訪問目標對象,這樣可以在不修改原目標對象的前提下,提供額外的功能操作,擴展目標對象的功...
閱讀 1256·2023-04-26 02:38
閱讀 943·2023-04-25 20:13
閱讀 3597·2021-11-19 11:31
閱讀 2403·2019-08-30 15:55
閱讀 2730·2019-08-30 14:11
閱讀 3166·2019-08-30 13:45
閱讀 1382·2019-08-29 18:41
閱讀 1155·2019-08-29 16:18