zoukankan      html  css  js  c++  java
  • Proxy代理对象是如何调用invoke()方法的.

    直奔主题,不说废话.先看java使用Proxy创建代理对象的代码.

    //一个开发者接口
    public
    interface Developer { String code(); void debug(); }
    //一个具体的开发者,实现两个接口
    public
    class JavaDeveloper implements Developer { private String name; public JavaDeveloper(String name) { this.name = name; } @Override public String code() { System.out.println(name + "写代码"); return "写好了"; } @Override public void debug() { System.out.println(name + "调试bug"); } }
    public class JavaDynamicProxy {
        public static void main(String[] args) {
            /*这个根据情况自行输入,主要功能是将生成出的代理对象Class文件存到本地.
            我用的idea编辑器,最终生成的文件在 工作空间下的 com\sun\proxy 文件夹中*/
            System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
    
            //具体类,需要增强的类
            JavaDeveloper zack = new JavaDeveloper("Zack");
            /*Proxy.newProxyInstance 方法三个参数
             * 1 一个类加载器
             * 2 需要增强的类都实现了哪些接口,或哪些父类.这个很重要,因为最终生成的代理类,是要重写父类的方法的.
             * 3 一个调用处理器.是一个接口,需要实现接口中的方法,就一个invoke().这个方法很重要,你使用代理对象中的方法,
             * 每次都会经过这个方法.这也就是增强的核心.invoke()的三个参数
             *   1 需要增强原始对象.这里需要指定一个原型方法.
             *   2 即将执行的增强方法,这个Method 当你调用代理对象的A方法,这个Method就是A方法的Class对象.
             *   3 方法参数.A方法的参数. 熟悉反射的朋友应该能理解,一个Method方法执行,需要一个实例对象,和方法参数列表.
             * */
    
            Developer zackProxy = (Developer) Proxy.newProxyInstance(zack.getClass().getClassLoader(),
                    zack.getClass().getInterfaces(), new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            /* 我这里分别对两个方法进行了不同的增强.需要注意的是 返回值
                             *  如果你的方法没有返回值可以 return null*/
                            if (method.getName().equals("code")) {
                                System.out.println("正在祈祷.....");
                                method.invoke(zack, args);
                                return "动态的写好了";
                            }
                            if (method.getName().equals("debug")) {
                                System.out.println("已经祈祷了,怎么还有bug");
                                method.invoke(zack, args);
                            }
                            return null;
                        }
                    });
            //使用代理对象
            String s = zackProxy.code();
            zackProxy.debug();
            System.out.println(s);
    
          /*打印结果
            正在祈祷.....
            Zack写代码
            已经祈祷了,怎么还有bug
            Zack调试bug
            动态的写好了*/
        }
    }

    我这里不关注代理对象的生成.有兴趣的可以自行查看.下边是生成代理对象的Class源文件,经过反编译后.


    /*注意 当前反编译文件其中还有hashCode()toString()equals(Object obj)三个Object的方法.
    这三个方法都是Object中可以被覆盖的方法.这也就是Proxy.newProxyInstance()方法第二个参数
    的作用.*/
    public final class $Proxy0 extends Proxy
    implements Developer {


      //这里我把object的方法去掉了.直奔主题
    private static Method m3;//debug 自定义的方法
    private static Method m4;//code 自定义的方法


    static {
    try {
    //初始化了两个Method,通过类名创建Class对象,在通过方法名获取Method对象.
    m3 = Class.forName("sis.proxytest.Developer").getMethod("debug", new Class[0]);
    m4 = Class.forName("sis.proxytest.Developer").getMethod("code", new Class[0]);
    } catch (NoSuchMethodException nosuchmethodexception) {
    throw new NoSuchMethodError(nosuchmethodexception.getMessage());
    } catch (ClassNotFoundException classnotfoundexception) {
    throw new NoClassDefFoundError(classnotfoundexception.getMessage());
    }
    }

    public $Proxy0(InvocationHandler invocationhandler) {
    // 这里我把父类也就是 Proxy 部分代码贴上.
    // protected InvocationHandler h;//父类成员变量
    // protected Proxy(InvocationHandler h) {//父类构造子
    // Objects.requireNonNull(h);
    // //就是把我们new出来的 InvocationHandler传递给了父类
    // this.h = h;
    // }
    super(invocationhandler);
    }

    //这才是重点
    public final void debug() {
    try {
    /* 当我们使用代理对象调用 debug()方法时.会使用父类Proxy的h成员变量的invoke()
    这个h就是我们开篇使用Proxy.newProxyInstance创建代理对象中的第三个参数*/
    super.h.invoke(this, m3, null);
    return;
    } catch (Error) {
    } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
    }
    }

    public final String code() {
    try {
    return (String) super.h.invoke(this, m4, null);
    } catch (Error) {
    } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
    }
    }
    }

    以上就是Proxy生成代理对象,是如果使用invoke()方法的过程.如有不足请补充.

  • 相关阅读:
    python 2 和 python 3 的区别
    random模块、time模块、sys模块、os模块
    正则表达式
    生成器 推导式 生成器表达式
    免费的论文查重网站
    Django 13
    pycharm连接mysql出错解决方案
    前端 51
    前端 50
    前段 49
  • 原文地址:https://www.cnblogs.com/zumengjie/p/11301956.html
Copyright © 2011-2022 走看看