Design Pattern: Proxy, dynamic Proxy
代理模式
Proxy Pattern's 3 roles:
1. (abstract common)Subject:common interface
2. ProxySubject:含有the reference to the RealSubject //delegation
3. RealSubject:實現邏輯的類
類圖如下:
圖1
Java 動態代理
從JDK1.3開始,Java就引入了動態代理的概念。動態代理(Dynamic Proxy)可以幫助你減少代碼行數,真正提高代碼的可復用度。
類圖如下:
圖2
動態代理和普通的代理模式的區別,就是動態代理中的代理類是由java.lang.reflect.Proxy類在運行期時根據接口定義,采用Java反射功能動態生成的(圖2的匿名實現類)。和java.lang.reflect.InvocationHandler結合,可以加強現有類的方法實現。如圖2,圖中的自定義Handler實現InvocationHandler接口,自定義Handler實例化時,將實現類傳入自定義Handler對象。自定義Handler需要實現invoke方法,該方法可以使用Java反射調用實現類的實現的方法,同時當然可以實現其他功能,例如在調用實現類方法前后加入Log。而Proxy類根據Handler和需要代理的接口動態生成一個接口實現類的對象。當用戶調用這個動態生成的實現類時,實際上是調用了自定義Handler的invoke方法。
下面是使用動態代理的步驟:
1. Client向Proxy請求一個具有某個功能的實例;
2. Proxy根據Subject,以自定義Handler創建一個匿名內部類,并返回給Client;
3. Client獲取該匿名內部類的引用,調用在Subject接口種定義的方法;
4. 匿名內部類將對方法的調用轉換為對自定義Handler中invoke方法的調用
5. invoke方法根據一些規則做處理,如記錄log,然后調用SubjectImpl中的方法
Examples
Here is a simple example that prints out a message before and after a method invocation on an object that implements an arbitrary list of interfaces:
public interface Foo { Object bar(Object obj) throws BazException; } public class FooImpl implements Foo { Object bar(Object obj) throws BazException { // ... } } public class DebugProxy implements java.lang.reflect.InvocationHandler { private Object obj; public static Object newInstance(Object obj) { return java.lang.reflect.Proxy.newProxyInstance( obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new DebugProxy(obj)); } private DebugProxy(Object obj) { this.obj = obj; } public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { Object result; try { System.out.println("before method " + m.getName()); result = m.invoke(obj, args); } catch (InvocationTargetException e) { throw e.getTargetException(); } catch (Exception e) { throw new RuntimeException("unexpected invocation exception: " + e.getMessage()); } finally { System.out.println("after method " + m.getName()); } return result; } }To construct a
DebugProxy
for an implementation of theFoo
interface and call one of its methods:Foo foo = (Foo) DebugProxy.newInstance(new FooImpl()); foo.bar(null);
posted on 2008-12-14 09:21 Xiaobo Sun 閱讀(397) 評論(0) 編輯 收藏 所屬分類: Java 、Design Pattern