每個代理都有一個與之關聯的調用句柄,只要代理的方法被調用時就會調用該句柄。根據通用的設計原則:接口定義類型、類定義實現,代理對象可以實現一個或多個接口,但是不能實現類。因為代理類沒有可以訪問的名稱,它們不能有構造函數,所以它們必須由工廠創建。清單 2 顯示了動態代理的最簡單的可能實現,它實現 Set 接口并把所有 Set 方法(以及所有 Object 方法)分派給封裝的 Set 實例。
清單 2. 包裝 Set 的簡單的動態代理
public class SetProxyFactory {
public static Set getSetProxy(final Set s) { return (Set) Proxy.newProxyInstance (s.getClass().getClassLoader(), new Class[] { Set.class }, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(s, args); } }); } }
SetProxyFactory 類包含一個靜態工廠方法 getSetProxy(),它返回一個實現了 Set 的動態代理。代理對象實際實現 Set ―― 調用者無法區分(除非通過反射)返回的對象是動態代理。SetProxyFactory 返回的代理只做一件事,把方法分派給傳遞給工廠方法的 Set 實例。雖然反射代碼通常比較難讀,但是這里的內容很少,跟上控制流程并不難 ―― 只要某個方法在 Set 代理上被調用,它就被分派給調用句柄,調用句柄只是反射地調用底層包裝的對象上的目標方法。當然,絕對什么都不做的代理可能有點傻,是不是呢?