靜態代理是由咱們編寫好的類,在程序運行以前就已經編譯好的的類,此時就叫靜態代理。 說理論仍是比較懵逼的,直接上代碼:java
抽象主題,能夠想象成咱們的業務接口。設計模式
/** * 抽象主題。 * @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("我記錄一下啓動校驗後的相關日誌。"); } }
咱們使用靜態代理後,來試試看這種方式能不能行?測試代碼:this
public class Main{ public static void main(String[] args) throws ApiException { ProxySubject proxy = new ProxySubject(new RealSubject()); proxy.enableCheck(); } }
運行結果:設計
我記錄一下啓動校驗前的相關日誌 我開啓了某項校驗~~ 我記錄一下啓動校驗後的相關日誌。
靜態代理模式相對比較簡單,可是缺點確定也是有的:代理
一個代理對象只能服務於一個類。若是有不少類須要記錄日誌的話,你的一個一個去實現。。累不死你。。日誌
代理對象必須實現接口,如上。一個字:仍是累。code
這裏動態代理使用的是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!