设计模式之代理模式(上) 静态代理与JDK动态代理
2019獨角獸企業重金招聘Python工程師標準>>>
代理模式
- 給某一個對象提供一個代理,并由代理對象控制對原對象的引用。
靜態代理
靜態代理是由我們編寫好的類,在程序運行之前就已經編譯好的的類,此時就叫靜態代理。 說理論還是比較懵逼的,直接上代碼:
抽象主題,可以想象成我們的業務接口。
/*** 抽象主題。* @author wushuaiping* @date 2018/3/13 下午10:13*/ public interface ISubject {/*** 比如現在有個業務功能,需要開啟某項校驗。*/void enableCheck(); }真實主題,可以想象成我們對業務接口的實現類。
/*** 真實主題* @author wushuaiping* @date 2018/3/13 下午10:21*/ public class RealSubject implements ISubject {public void enableCheck() {System.out.println("我開啟了某項校驗~~");} }但是有一天,我突然想加個日志記錄,但是我不想去改動原有的方法。那么我們就可以使用這種方式:
/*** 代理類* @author wushuaiping* @date 2018/3/13 下午10:23*/ public class ProxySubject implements ISubject{private ISubject subject;public ProxySubject(ISubject subject){super();this.subject = subject;}// 對被代理對象的方法進行增強public void enableCheck() {before();subject.enableCheck();after();}private void before(){System.out.println("我記錄一下啟動校驗前的相關日志。");}private void after(){System.out.println("我記錄一下啟動校驗后的相關日志。");} }我們使用靜態代理后,來試試看這種方式能不能行?測試代碼:
public class Main{public static void main(String[] args) throws ApiException {ProxySubject proxy = new ProxySubject(new RealSubject());proxy.enableCheck();} }運行結果:
我記錄一下啟動校驗前的相關日志 我開啟了某項校驗~~ 我記錄一下啟動校驗后的相關日志。靜態代理模式相對比較簡單,但是缺點肯定也是有的:
一個代理對象只能服務于一個類。如果有很多類需要記錄日志的話,你的一個一個去實現。。累不死你。。
代理對象必須實現接口,如上。一個字:還是累。
動態代理
這里動態代理使用的是JDK的動態代理實現的,JDK的動態代理必須是目標對象實現接口才可以。也就是相當于我們上面的業務實現類(RealSubject)。使用CGLIB就不用實現接口也可完成動態代理,但是今天時間不多了,明天還得搬磚,所以先把JDK動態代理學了,明天再學學CGLIB的動態代理。 代碼如下:
要實現動態代理;需要先去實現InvocationHandler接口,這個接口提供了invoke方法,該方法相信用過反射或者AOP的同學應該都比較熟悉,我這里就不多講了。實現了這個后我們可以調用目標方法了,但是我們需要代理的對象還不知道從何而來,所以我們還需要使用JDK提供的Proxy.newProxyInstance方法,第一個參數是目標代理類的類加載器,第二個參數是目標代理類實現的接口,第三個參數的話是目標代理類的調用處理程序就是InvokeHandler啦。用該方法可以生產代理對象。
/*** 使用Java的動態代理實現* @author wushuaiping* @date 2018/3/13 下午10:43*/ public class DynamicProxy implements InvocationHandler {private Object target;public Object getProxyInstance(Object target){this.target = target;// 使用Java的獲取代理實例方法來獲取代理實例。。好繞啊。。反正就是獲取代理實例-_-return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this);}// 增強, 調用目標方法public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {before();// 因為我們需要被增強的方法enableCheck是沒有返回參數的,所以不需要返回值。// 如果有返回值 Object res = method.invoke(proxy, args); return res;就可以了method.invoke(target, args);after();return null;}private void before(){System.out.println("操作之前的日志記錄~~");}private void after(){System.out.println("操作之后的日志記錄~~");} }Test case
public static void main(String[] args) throws ApiException {DynamicProxy proxy = new DynamicProxy();ISubject subject = (ISubject)proxy.getProxyInstance(new RealSubject());subject.enableCheck();}運行結果:
操作之前的日志記錄~~ 我開啟了某項校驗~~ 操作之后的日志記錄~~今天的設計模式算是學完啦,抽象工廠模式感覺我可能思維不夠抽象,所以到現在還沒能理解抽象工廠模式到底能干嘛?實際中有何用處?本文用于個人學習記錄,有寫的不好的地方,還請各位大佬指點一二!
good night!
轉載于:https://my.oschina.net/u/3152087/blog/1634283
總結
以上是生活随笔為你收集整理的设计模式之代理模式(上) 静态代理与JDK动态代理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 个人博客开发-开篇
- 下一篇: Avalonia Beta 1对WPF做