博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Proxy代理对象是如何调用invoke()方法的.
阅读量:4582 次
发布时间:2019-06-09

本文共 4077 字,大约阅读时间需要 13 分钟。

直奔主题,不说废话.先看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()方法的过程.如有不足请补充.

转载于:https://www.cnblogs.com/zumengjie/p/11301956.html

你可能感兴趣的文章
jQ判断checked是否选中
查看>>
AngularJS Scope(作用域)
查看>>
js进阶 offset
查看>>
c语言判断打开文件是否为空的方法
查看>>
第三章 数据类型和运算符
查看>>
力扣—— 最大三角形面积
查看>>
EFDB 基本规范&知识
查看>>
在安装程序之前,预先安装别的程序
查看>>
进程查看
查看>>
react插件(参考)
查看>>
docker中 CMD 与 ENTRYPOINT 的区别
查看>>
Aizu2130-Billion Million Thousand-dp
查看>>
网站推荐的代码自动生成软件实际使用感触
查看>>
JVM系列五:JVM监测&工具
查看>>
mysql Partition(分区)初探
查看>>
JavaScript高级编程II
查看>>
Response.Redirect 打开新窗体的两种方法
查看>>
全然二叉树与满二叉树
查看>>
js设计模式(二)---策略模式
查看>>
文件被写入后,但未关闭流,却又打开输入流,当然有问题。。
查看>>