首先聲明,本爲並非原創,大量參考自http://layznet.iteye.com/blog/1182924,一方面做個備份,另一方面也是自己學習的過程。
一、代理
對一個類(委託類,實際完成工作的那個類)方法的調用交給另一個類(代理類,可以靜態或動態生成)來完成。如果委託類和代理類實現了同一個接口,那麼代理就可以很方便的完成。
二、靜態代理
程序運行前代理類和委託類的關係就已經確定,代理類的字節碼文件已經存在,代理不是運行時生成。
Code list 1, 接口定義:
package proxy.staticy; public interface Subject { void dealTask(String taskName); }
Code list 2,委託類,真正做事情的類:
package proxy.staticy; public class RealSubject implements Subject { @Override public void dealTask(String taskName) { System.out.println("正在執行任務: " + taskName); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }
Code list 3,代理類:
package proxy.staticy; public class ProxySubject implements Subject { private Subject delegate; public ProxySubject(Subject delegate) { this.delegate = delegate; } @Override public void dealTask(String taskName) { long start = System.currentTimeMillis(); delegate.dealTask(taskName); long end = System.currentTimeMillis(); System.out.println("任務耗時" + (end - start) + "毫秒"); } }
Code list 4,生成代理的工廠類:
package proxy.staticy; public class SubjectStaticFactory { public static Subject getInstance() { return new ProxySubject(new RealSubject()); } }
Code list 5,模擬客戶端:
package proxy.staticy; public class Client1 { public static void main(String[] args) { Subject myProxy = SubjectStaticFactory.getInstance(); myProxy.dealTask("Task one"); } }
三、動態代理
代理類的源碼在運行時有虛擬機反射生成,因此不存在字節碼文件,代理類和委託類的關係在運行時確定。
Code list 6,動態代理對應的調用處理器:(說白了就是類似於代理的類)
/** * 動態代理對應的調用處理器 */ package proxy.dynamic; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class SubjectInvocationHandler implements InvocationHandler { // 代理類持有一個委託類的對象引用 private Object delegate; public SubjectInvocationHandler(Object delegate){ this.delegate = delegate; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long start = System.currentTimeMillis(); // Method的invoke返回Object對象方法執行的結果 method.invoke(delegate, args); long end = System.currentTimeMillis(); System.out.println("任務執行耗時"+(end - start)+"毫秒"); return null; } }
Code list 7,生成動態代理對象的工廠類:
/** * 生成動態代理對象的工廠. */ package proxy.dynamic; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import proxy.staticy.RealSubject; import proxy.staticy.Subject; /** * 客戶端調用此方法獲得代理對象, * 對客戶端來說,並不知道獲取的是代理對象還是委託對象。 */ public class DynamicProxyFactory { public static Subject getInstance() { Subject delegate = new RealSubject(); InvocationHandler handler = new SubjectInvocationHandler(delegate); Subject proxy = (Subject) Proxy.newProxyInstance( delegate.getClass().getClassLoader(), new Class[] {Subject.class}, handler); return proxy; } }
Code list 8,模擬客戶端:
package proxy.dynamic; import proxy.staticy.Subject; public class Client2 { public static void main(String[] args) { Subject myProxy = DynamicProxyFactory.getInstance(); myProxy.dealTask("Task two"); } }