
文章插圖
這篇文章解決三個問題:
1.What 動態(tài)代理是什么
2.How 動態(tài)代理怎么用
3.Why 動態(tài)代理的原理
動態(tài)代理是什么?
動態(tài)代理是代理模式的一種具體實現(xiàn),是指在程序運行期間,動態(tài)的生成目標(biāo)對象的代理類(直接加載在內(nèi)存中的字節(jié)碼文件),實現(xiàn)對目標(biāo)對象所有方法的增強 。通過這種方式,我們可以在不改變(或無法改變)目標(biāo)對象源碼的情況下,對目標(biāo)對象的方法執(zhí)行前后進行干預(yù) 。
動態(tài)代理怎么用?
首先,準(zhǔn)備好我們需要代理的類和接口,因為JDK的動態(tài)代理是基于接口實現(xiàn)的,所以被代理的對象必須要有接口 。
/*** SaySomething接口*/public interface SaySomething {public void sayHello();public void sayBye();}/*** SaySomething的實現(xiàn)類*/public class SaySomethingImpl implements SaySomething {@Overridepublic void sayHello() {System.out.println("Hello World");}@Overridepublic void sayBye() {System.out.println("Bye Bye");}}按照動態(tài)代理的用法,需要自定義一個處理器,用來編寫自定義邏輯,實現(xiàn)對被代理對象的增強 。
自定義的處理器需要滿足以下要求:
- 需要實現(xiàn)InvocationHandler,重寫invoke方法,在invoke方法中通過加入自定義邏輯,實現(xiàn)對目標(biāo)對象的增強 。
- 需要持有一個成員變量,成員變量的是被代理對象的實例,通過構(gòu)造參數(shù)傳入 。(用來支持反射調(diào)用被代理對象的方法)
- 需要提供一個參數(shù)為被代理對象接口類的有參構(gòu)造 。(用來支持反射調(diào)用被代理對象的方法)
/*** 自定義的處理器,用來編寫自定義邏輯,實現(xiàn)對被代理對象的增強*/public class CustomHandler implements InvocationHandler {//需要有一個成員變量,成員變量為被代理對象,通過構(gòu)造參數(shù)傳入,用來支持方法的反射調(diào)用 。private SaySomething obj;//需要有一個有參構(gòu)造,通過構(gòu)造函數(shù)將被代理對象的實例傳入,用來支持方法的反射調(diào)用public CustomHandler(SaySomething obj) {this.obj = obj;}/*** proxy:動態(tài)生成的代理類對象com.sun.proxy.$Proxy0* method:被代理對象的真實的方法的Method對象* args:調(diào)用方法時的入?yún)?/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//目標(biāo)方法執(zhí)行前的自定義邏輯處理System.out.println("-----before------");//執(zhí)行目標(biāo)對象的方法,使用反射來執(zhí)行方法,反射需要傳入目標(biāo)對象,此時用到了成員變量obj 。Object result = method.invoke(obj, args);//目標(biāo)方法執(zhí)行后的自定義邏輯處理System.out.println("-----after------");return result;}}這樣我們就完成了自定義處理器的編寫,同時在invoke方法中實現(xiàn)對了代理對象方法的增強,被代理類的所有方法的執(zhí)行都會執(zhí)行我們自定義的邏輯 。
接下來,需要通過Proxy,newProxyInstance()方法來生成代理對象的實例,并進行方法調(diào)用測試 。
public class JdkProxyTest {public static void main(String[] args) {//將生成的代理對象的字節(jié)碼文件 保存到硬盤System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");//被代理對象的實例SaySomething obj = new SaySomethingImpl();//通過構(gòu)造函數(shù),傳入被代理對象的實例,生成處理器的實例InvocationHandler handler = new CustomHandler(obj);//通過Proxy.newProxyInstance方法,傳入被代理對象Class對象、處理器實例,生成代理對象實例SaySomething proxyInstance = (SaySomething) Proxy.newProxyInstance(obj.getClass().getClassLoader(),new Class[]{SaySomething.class}, handler);//調(diào)用生成的代理對象的sayHello方法proxyInstance.sayHello();System.out.println("===================分割線==================");//調(diào)用生成的代理對象的sayBye方法proxyInstance.sayBye();}}
以上關(guān)于本文的內(nèi)容,僅作參考!溫馨提示:如遇健康、疾病相關(guān)的問題,請您及時就醫(yī)或請專業(yè)人士給予相關(guān)指導(dǎo)!
「愛刨根生活網(wǎng)」www.malaban59.cn小編還為您精選了以下內(nèi)容,希望對您有所幫助:
- Linux和Unix的那些事兒 UNIX和Linux
- 2 白酒起源探討:李白一頓能喝4斤,他們唐朝人喝的到底是啥酒
- 絲瓜最好吃的簡單做法 絲瓜怎么好吃又簡單的做法
- 刷牙究竟能不能省心?100天一充的T9U電動牙刷使用體驗
- 電動牙刷的正確使用方法 電動牙刷的正確使用方法圖片
- 判斷一條魚的年齡 怎么判斷一條魚的年齡
- 多數(shù)情況下通過什么判斷魚的年齡 多數(shù)情況下通過什么來判斷魚的年齡
- 你知道怎么識別魚的年齡嗎 如何識別魚的年齡
- 紅瑪瑙的魅力 什么樣的紅瑪瑙
- 用鮭魚精子制造的塑料替代品來了,可以被水回收
