java的動態(tài)代理在接java的api上有說明,這里就不寫了。我理解的代理:
對特定接口中特定方法的功能進(jìn)行擴(kuò)展,這就是代理。代理是通過代理實(shí)例關(guān)聯(lián)的調(diào)用處理程序?qū)ο笳{(diào)用方法。
下面通過一個例子看一下:
接口:
public interface Num {  void show();    int getNum();    int getProduct(int x);}實(shí)現(xiàn)類:
public class MyNum implements Num {  @Override  public int getNum() {    return 3;  }    @Override  public int getProduct(int x) {    return x;  }  @Override  public void show() {    System.out.println("底層方法打印數(shù)字99");  }}先看一下Method中的invoke方法在api中是怎么描述的
就是說調(diào)用處理程序?qū)涌诘膶?shí)現(xiàn)類對象調(diào)用Method對象表示的底層方法。
第一種實(shí)現(xiàn)代理的方式:
public class NumProxy {  private Object num;  //通過構(gòu)造方法構(gòu)造接口的實(shí)現(xiàn)類對象  public NumProxy(Object num) {    this.num = num;  }  public Object getNumByProxy(){    Object numProxy = Proxy.newProxyInstance(num.getClass().getClassLoader(), new Class[]{Num.class}, new InvocationHandler() {      /**       * method: 對應(yīng)于在代理實(shí)例上調(diào)用的接口方法的 Method 實(shí)例。我理解的就是被代理的真實(shí)方法實(shí)例       * args: 我理解的是真實(shí)方法的參數(shù)數(shù)組       */      @Override      public Object invoke(Object proxy, Method method, Object[] args)          throws Throwable {        Object obj = null;        System.out.println("在方法之前開始記錄");        String methodName = method.getName();        if("getProduct".equals(methodName)){          obj = method.invoke(num, args);          obj = (Integer) obj * 2;          System.out.println("proxy: getProduct()結(jié)束");        }        else if("show".equals(methodName)){          obj = method.invoke(num, args);          System.out.println("proxy: show()結(jié)束");        }        return obj;      }    });    return numProxy;  }}第二種實(shí)現(xiàn)代理的方式:通過實(shí)現(xiàn)InvocationHandler接口
public class NumProxyImpl implements InvocationHandler {  //這里我把接口類型具體化了, 沒有寫成Object  private Num num;    public NumProxyImpl(Num num){    this.num = num;  }    @Override  public Object invoke(Object proxy, Method method, Object[] args)      throws Throwable {    Object obj = null;    String methodName = method.getName();    if("getProduct".equals(methodName)){      System.out.println("proxy: getProduct()開始");      obj = method.invoke(num, args);      obj = (Integer) obj * 2;      System.out.println("proxy: getProduct()結(jié)束");    }else if("show".equals(methodName)){      System.out.println("proxy: show()開始");      obj = method.invoke(num, args);      System.out.println("proxy: show()結(jié)束");    }    return obj;  }}測試代碼:
public class TestNum {  public static void main(String[] args) {    //兩種方式一起測試    NumProxy np = new NumProxy(new MyNum());    Num numProxy = (Num) np.getNumByProxy();    int x = numProxy.getProduct(2);    System.out.println(x);    numProxy.show();        System.out.println("----------------");    NumProxyImpl npi = new NumProxyImpl(new MyNum());    Num numPro = (Num) Proxy.newProxyInstance(Num.class.getClassLoader(), new Class[]{Num.class}, npi);    int n = numPro.getProduct(3);    System.out.println(n);    numPro.show();  }}控制臺結(jié)果:
第二種方式有點(diǎn)小疑惑,不知道大家有沒有,那就是并沒有顯示的調(diào)用NumProxyImpl中的invoke方法,可是卻執(zhí)行了,嗯嗯,這個自己下去看一下啊
不想麻煩的只需要記住就行了。
比如編碼的處理就可以用到代理,下次寫個例子。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。
新聞熱點(diǎn)
疑難解答
圖片精選