Java SE 是什么,包括哪些内容(十七)?
本文内容参考自Java8标准
再次感谢Java编程思想对本文的启发!
上一篇博文中详细说明了动态代理的内容,但是在说到调用处理器InvocationHandler的时候,有一个Object类型的参数proxy却没有用到。现在详细解释这个参数到底是干什么的。
我们来回顾一下调用处理器的代码(它是动态代理中一个固定的接口):
// 调用处理器
//类MyHandler实现了接口InvocationHandler,这是动态代理的硬性规定。就得这么来
//类似,如果你想拥有比较的能力,就得实现Comparable接口等
public class MyHandler implements InvocationHandler{
//被代理类对象的实例(在这个示例中指的就是被代理类Person的实例)
private Object obj;
//构造方法,带一个Object类型的形式参数
public MyHandler(Object obj){
//对象初始化(赋值)
this.obj = obj;
}
//方法invoke,形式参数分别是
//Obeject类型的proxy(我们现在重点需要关注的参数!)
//Method类型的method(代表的是运行时调用的那个方法)
//Object数组类型的args(代表的是运行时调用的那个方法的实际参数,可能一个或者多个,
//所以是数组类型)
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable{
//可能还有其他的代码...
//通过Java的反射执行方法method(如果这里不明白,可以去找到我有关反射的博文,
//了解如何通过反射执行一个方法).
method.invoke(obj, args);
//可能还有其他的代码...
//返回null
return null;
}
}
从上面的代码中,我们可以知道InvocationHandler接口中只有一个方法:invoke,它具有三个参数:
①、Object类型的proxy
②、Method类型的method
③、Object数组类型的args
其中Method类型的method参数代表的是实际运行时调用的方法(通过反射),Object数组类型的args参数代表的是实际运行时调用的方法的所有参数(通过反射)。唯一剩下的未被使用的参数是Object类型的proxy。
我们先从InvocationHandler接口的源码中找一找答案:
从源码的解释中,我们可以知道proxy代表的是代理类的对象实例(一定要注意,代表的是代理类,不是被代理类!)。
再回到上一篇博文中的代码:
从测试的代码中我们可以看到:最终使用的时候,是通过创建代理类的实例去调用目标方法。
所以,我们可以得出一个结论:
InvocationHandler接口的方法中,有一个专门代表代理类引用的参数,它就是Object类型的proxy。
主要有以下两个作用:
①、使用反射获取代理对象的信息(比如proxy.getClass().getName())。
②、返回代理对象以进行连续调用。
代码示例:
①、获取代理对象的信息:
运行结果:
从代码和结果上看,这个参数是可以直接使用的,不需要再做额外的处理!
②、返回代理对象以连续调用:
要实现这个功能,首先你需要保证接口中的方法有返回值,并且返回的是接口类型!如果你调用返回类型是void的方法,是无法产生这种效果的。
代码示例:
接口中的方法返回接口类型:
调用处理器中返回代理对象的引用:
测试:
PS:时间有限,有关Java SE的内容会持续更新!今天就先写这么多,如果有疑问或者有兴趣,可以加QQ:2649160693,并注明CSDN,我会就博文中有疑义的问题做出解答。同时希望博文中不正确的地方各位加以指正