首页 > 编程 > Java > 正文

详解java动态代理的2种实现方式

2019-11-26 13:30:31
字体:
来源:转载
供稿:网友

java的动态代理在接java的api上有说明,这里就不写了。我理解的代理:

对特定接口中特定方法的功能进行扩展,这就是代理。代理是通过代理实例关联的调用处理程序对象调用方法。

下面通过一个例子看一下:

接口:

public interface Num {  void show();    int getNum();    int getProduct(int x);}

实现类:

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("底层方法打印数字99");  }}

先看一下Method中的invoke方法在api中是怎么描述的

就是说调用处理程序对接口的实现类对象调用Method对象表示的底层方法。

第一种实现代理的方式:

public class NumProxy {  private Object num;  //通过构造方法构造接口的实现类对象  public NumProxy(Object num) {    this.num = num;  }  public Object getNumByProxy(){    Object numProxy = Proxy.newProxyInstance(num.getClass().getClassLoader(), new Class[]{Num.class}, new InvocationHandler() {      /**       * method: 对应于在代理实例上调用的接口方法的 Method 实例。我理解的就是被代理的真实方法实例       * args: 我理解的是真实方法的参数数组       */      @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()结束");        }        else if("show".equals(methodName)){          obj = method.invoke(num, args);          System.out.println("proxy: show()结束");        }        return obj;      }    });    return numProxy;  }}

第二种实现代理的方式:通过实现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()结束");    }else if("show".equals(methodName)){      System.out.println("proxy: show()开始");      obj = method.invoke(num, args);      System.out.println("proxy: show()结束");    }    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();  }}

控制台结果:

第二种方式有点小疑惑,不知道大家有没有,那就是并没有显示的调用NumProxyImpl中的invoke方法,可是却执行了,嗯嗯,这个自己下去看一下啊

不想麻烦的只需要记住就行了。

比如编码的处理就可以用到代理,下次写个例子。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表