:: 首頁(yè) ::  :: 聯(lián)系 :: 聚合  :: 管理

          AOP基礎(chǔ):動(dòng)態(tài)代理

          Posted on 2009-11-07 21:27 codingliyi 閱讀(258) 評(píng)論(0)  編輯  收藏 所屬分類: Design Patterns

          在了解動(dòng)態(tài)代理之前,有必要先知道什么是靜態(tài)代理。

          1. 靜態(tài)代理

          在靜態(tài)代理的實(shí)現(xiàn)中,代理對(duì)象與被代理對(duì)象都必須實(shí)現(xiàn)同一個(gè)借口,在代理對(duì)象中可以實(shí)現(xiàn)日志記錄等相關(guān)服務(wù),并在需要的時(shí)候在呼叫被代理對(duì)象。如此代理對(duì)象中就可以僅保留業(yè)務(wù)相關(guān)職責(zé)。

          示例代碼:

          首先定義一個(gè)IHello接口:

          1public interface IHello {
          2        public void sayHello(String name);
          3}
          然后讓實(shí)現(xiàn)業(yè)務(wù)邏輯的HelloSpeaker類實(shí)現(xiàn)IHello接口:
          1public class HelloSpeaker implements IHello {
          2    public void sayHello(String name) {
          3            System.out.println("Hello, " + name);
          4    }

          5}
          將日志記錄功能放入代理對(duì)象中,代理對(duì)象同樣也要實(shí)現(xiàn)IHello接口:
           1import java.util.logging.*;
           2
           3public class HelloSpeakerProxy implements IHello {
           4    
           5    private Logger logger = Logger.getLogger(this.getClass().getName());
           6    private IHello helloObject;
           7    
           8    public HelloSpeakerProxy(IHello hello){;
           9        this.helloObject = hello;
          10    }

          11    public void sayHello(String name) {
          12        logger.log(Level.INFO, "before sayHello");
          13        helloObject.sayHello(name);
          14        logger.log(Level.INFO, "after sayHello");
          15    }

          16}
          編寫測(cè)試程序:
           1public class StaticProxyDemo {
           2    public static void main(String[] args) {
           3        HelloSpeakerProxy proxy = new HelloSpeakerProxy(new HelloSpeaker());
           4        proxy.sayHello("codingliyi");
           5    }

           6//    運(yùn)行結(jié)果:
           7//    2009-11-7 21:21:55 SpringAOP.HelloSpeakerProxy sayHello
           8//    信息: before sayHello
           9//    Hello, codingliyi
          10//    2009-11-7 21:21:55 SpringAOP.HelloSpeakerProxy sayHello
          11//    信息: after sayHello
          12}

          靜態(tài)代理缺陷:代理對(duì)象的一個(gè)接口只服務(wù)于一種類型的被代理對(duì)象。如果要代理的方法很多,靜態(tài)代理就無(wú)法勝任。

          2. 動(dòng)態(tài)代理

          JDK1.3之后加入了可協(xié)助開(kāi)發(fā)動(dòng)態(tài)代理功能的API,不必為特定對(duì)象與方法編寫特定的代理對(duì)象。使用動(dòng)態(tài)代理,可以使得一個(gè)處理者(Handler)服務(wù)于各個(gè)對(duì)象。

          相關(guān)的接口和類有如下兩個(gè):

          1.java.lang.reflect.InvocationHandler接口

          該接口僅定義了一個(gè)方法:

          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable

          其中,proxy指代理類,method是被代理的方法,args指方法的參數(shù)。

          2.java.lang.reflect.Proxy;

          該類最主要的方法:

          static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

          其中,loader指被代理類的類加載器;interfaces指被代理類實(shí)現(xiàn)的接口,h指方法調(diào)用的處理程序。

          動(dòng)態(tài)代理的示例代碼如下:

          DynamicProxyHandler.java
           1public class DynamicProxyHandler implements InvocationHandler {
           2    private Object delegate;
           3    
           4    public DynamicProxyHandler(Object delegate){
           5        this.delegate = delegate;
           6    }

           7    
           8    public Object invoke(Object proxy, Method method, Object[] args)
           9            throws Throwable {
          10        System.out.println("調(diào)用方法前");
          11        Object result = method.invoke(delegate,args);
          12        System.out.println("調(diào)用方法后");
          13        return result;
          14    }

          15}
          DynamicProxyDemo.java
           1public class DynamicProxyDemo {
           2    public static void main(String[] args) {
           3        HelloSpeaker speaker = new HelloSpeaker();
           4        IHello hello = (IHello)Proxy.newProxyInstance(speaker.getClass().getClassLoader(), speaker.getClass().getInterfaces(), new DynamicProxyHandler(speaker));
           5        hello.sayHello("codingliyi");
           6    }

           7//    運(yùn)行結(jié)果:
           8//    調(diào)用方法前
           9//    Hello, codingliyi
          10//    調(diào)用方法后
          11}

          動(dòng)態(tài)代理的實(shí)戰(zhàn)步驟:
          a.    業(yè)務(wù)接口,一個(gè)Interface;
          b.    實(shí)現(xiàn)業(yè)務(wù)接口的類,即被代理類;
          c.    一個(gè)繼承了java.lang.reflect.InvocationHandler的Handler類,里面維持了一個(gè)被代理對(duì)象的引用(Object類型),實(shí)現(xiàn)invoke()方法;
          d.    使用Proxy.newProxyInstance()將Handler與被代理類關(guān)聯(lián),得到代理類,并強(qiáng)制轉(zhuǎn)化為接口類型;
          e.    調(diào)用該接口的方法。

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 循化| 呼和浩特市| 南投县| 彰化县| 义乌市| 台南市| 高尔夫| 洱源县| 柞水县| 灵川县| 浦城县| 合水县| 乐山市| 莒南县| 陕西省| 栾川县| 都兰县| 盖州市| 武定县| 秦皇岛市| 海丰县| 海安县| 澄迈县| 互助| 新沂市| 衡东县| 玛多县| 维西| 临夏县| 阳曲县| 墨江| 怀柔区| 长白| 江油市| 瑞丽市| 汨罗市| 凤阳县| 左贡县| 广水市| 繁昌县| 嘉义市|