欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2024-03-09 15:33:29
java的动态代理在接java的api上有说明,这里就不写了。我理解的代理: 对特定接口中特定方法的功能进行扩展,这就是代理。代理是通过代理实例关联的调用处理程序对象调用...

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中是怎么描述的详解java动态代理的2种实现方式

就是说调用处理程序对接口的实现类对象调用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();
  }
}

控制台结果:
详解java动态代理的2种实现方式

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

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

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

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