本文講述代理模式... 代理模式的作用是:為其他對象提供一種代理以控制對這個對象的訪問。
代理模式一般涉及到的角色有:
下面四個類講述一個簡單的靜態(tài)代理,參見程序Subject.java,RealSubject.java,ProxySubject.java和Client.java。把他們放在一個包下即可,代碼如下:
abstract public class Subject{ abstract public void request(); }
public class RealSubject extends Subject { public void request() { System.out.println("From real subject."); } }
public class ProxySubject extends Subject{ private RealSubject realSubject; // 以真實角色作為代理角色的屬性 public void request() // 該方法封裝了真實對象的request方法 { preRequest(); if (realSubject == null) { realSubject = new RealSubject(); } realSubject.request(); // 此處執(zhí)行真實對象的request方法 postRequest(); } private void preRequest() { System.out.println("先前做的事情"); } private void postRequest() { System.out.println("之后做的事情"); } }
public class Client{ public static void main(String[] args) { Subject sub = new ProxySubject(); sub.request(); } }
要有四個角色:抽象角色,代理角色,真實角色和客戶。在Java中要想對其他對象引用,生成一個那個對象的屬性就行了。比如本例中就是在ProxySubject類中聲明了RealSubject類的對象,作為一個屬性存在ProxySubject中。
由以上代碼可以看出,客戶實際需要調(diào)用的是RealSubject類的request()方法,現(xiàn)在用ProxySubject來代理 RealSubject類,同樣達到目的,同時還封裝了其他方法(preRequest(),postRequest()),可以處理一些其他問題。
下面講述動態(tài)代理。
Java動態(tài)代理類位于java.lang.reflect包下,一般主要涉及到以下兩個類(接口算作特殊類):
public object invoke(Object obj,Method method, Object[] args)
(2)Proxy:該類即為動態(tài)代理類,作用類似于上例中的ProxySubject,其中主要包含以下內(nèi)容:
protected Proxy(InvocationHandler h):構(gòu)造函數(shù),用于給內(nèi)部的h賦值;
static Class getProxyClass (ClassLoader loader, Class[] interfaces):獲得一個代理類,其中l(wèi)oader是類裝載器,interfaces是真實類所擁有的全部接口的數(shù)組;
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理類的一個實例,返回后的代理類可以當作被代理類使用(可使用被代理類的在Subject接口中聲明過的方法)。
所謂Dynamic Proxy是這樣一種class:它是在運行時生成的class,在生成它時你必須提供一組interface給它,然后該class就宣稱它實現(xiàn)了這些 interface。你當然可以把該class的實例當作這些interface中的任何一個來用。當然,這個Dynamic Proxy其實就是一個Proxy,它不會替你作實質(zhì)性的工作,在生成它的實例時你必須提供一個handler,由它接管實際的工作。
下面例子講述了一個動態(tài)代理Subject.java,RealSubject.java,DynamicSubject.java和Client.java,把他們放在一個包下,代碼如下:
//抽象角色(之前是抽象類,此處應改為接口) public interface Subject { public void request(); }
//具體角色 public class RealSubject implements Subject { public RealSubject() { } public void request() { System.out.println("真正做事的。"); } }
//代理處理器 /** * 該代理類的內(nèi)部屬性為Object類,實際使用時通過該類的構(gòu)造函數(shù)DynamicSubject(Object obj)對其賦值; * 此外,在該類還實現(xiàn)了invoke方法,該方法中的 method.invoke(sub,args); * 其實就是調(diào)用被代理對象的將要被執(zhí)行的方法,方法參數(shù)sub是實際的被代理對象, * args為執(zhí)行被代理對象相應操作所需的參數(shù)。 * 通過動態(tài)代理類,我們可以在調(diào)用之前或之后執(zhí)行一些相關(guān)操作 */ public class DynamicSubject implements InvocationHandler { private Object sub; public DynamicSubject() { } public DynamicSubject(Object obj) { sub = obj; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("調(diào)用前" + method); method.invoke(sub, args); System.out.println("調(diào)用后 " + method); return null; } }
//客戶端 public class Client { static public void main(String[] args) throws Throwable { RealSubject rs = new RealSubject(); // 在這里指定被代理類 InvocationHandler ds = new DynamicSubject(rs); Class<?> cls = rs.getClass(); // 以下是一次性生成代理 Subject subject = (Subject) Proxy.newProxyInstance( cls.getClassLoader(), cls.getInterfaces(), ds); subject.request(); } }
這個程序中把靜態(tài)代理類的抽象類改變?yōu)橐粋€接口,而實際類實現(xiàn)這個接口。是因為Proxy類的newProxyInstance方法傳入需要提供一個接口,這個是Java動態(tài)代理框架給我們設(shè)計好的了。本例的ProxySubject類實現(xiàn)了InvocationHandler接口及實現(xiàn)invoke方法,并且提供一個帶參數(shù)的構(gòu)造方法,通過Client類動態(tài)的調(diào)用真實類。
Client類通過DynamicSubject類生成真實類的代理對象,并經(jīng)由Proxy類的newProxyInstance方法實現(xiàn)生成“一個能做真實類做的事的代理”,并由該代理直接調(diào)用真實類所具有的方法。
OK,也許還會有些迷惑,不過不要緊,沒有什么高端的知識能夠一次就成功的,要勤于練習。
下面這個類作為參考,代碼如下:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.List; import java.util.Vector; public class VectorProxy implements InvocationHandler { private Object proxyobj; public VectorProxy(Object obj) { proxyobj = obj; } public static Object factory(Object obj) { Class<?> cls = obj.getClass(); return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), new VectorProxy(obj)); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before calling " + method); if (args != null) { for (int i = 0; i < args.length; i++) { System.out.println(args[i] + ""); } } Object object = method.invoke(proxyobj, args); System.out.println("after calling " + method); return object; } @SuppressWarnings("unchecked") public static void main(String[] args) { List<String> v = (List<String>) factory(new Vector<String>(10)); v.add("New"); v.add("York"); System.out.println(v); v.remove(0); System.out.println(v); } }
這個類看不明白不要緊,慢慢來。
下面也是一個演示程序,作為擴展知識用,一共五個類,在同一包下,代碼如下:
五個類Foo.java, FooImpl.java, FooImpl2.java, CommonInvocationHandler.java和Demo.java。
public interface Foo { void doAction(); }
public class FooImpl implements Foo { public FooImpl() { } public void doAction() { System.out.println("in FooImp1.doAction()"); } }
public class FooImpl2 implements Foo { public FooImpl2() { } public void doAction() { System.out.println("in FooImp2.doAction()"); } }
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class CommonInvocationHandler implements InvocationHandler { // 動態(tài)執(zhí)行對象,需要回調(diào)的對象 private Object target; // 支持構(gòu)造子注射 public CommonInvocationHandler() { } // 支持構(gòu)造子注射 public CommonInvocationHandler(Object target) { setTarget(target); } /** * * 采用setter方法注射 * * @param target * */ public void setTarget(Object target) { this.target = target; } /** * * 調(diào)用proxy中指定的方法method,并傳入?yún)?shù)列表args * * @param proxy * 代理類的類型,例如定義對應method的代理接口 * * @param method * 被代理的方法 * * @param args * 調(diào)用被代理方法的參數(shù) * * @return * * @throws java.lang.Throwable * */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(target, args); } }
|
|
來自: 碧海山城 > 《代理模式(與java的反射)》