本文共 3743 字,大约阅读时间需要 12 分钟。
此篇博客参考自:
和首先是讲这段代码的流程,以大明星刘德华为例,把代理当作他的“经纪人”
首先是person类:package com.Kit.proxy;public interface Person { //他又要唱歌和跳舞两种情况 String sing(String name); String dance(String name);}
LiuDeHua类:
package com.Kit.proxy;//这个明星继承了person这个接口,并且实现对应的方法public class LiuDeHua implements Person{ public String sing(String name) { System.out.println("刘德华唱"+name+"这首歌"); return "歌唱完了,谢谢大家"; } public String dance(String name) { System.out.println("刘德华跳"+name+"这支舞"); return "舞跳完了,谢谢大家"; }}
LiuDeHuaProxy类:
package com.Kit.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;//所以在这个例子当做,代理就相当于是经纪人的形式出现的public class LiuDeHuaProxy { //设计一个类变量记住代理类要代理的目标对象 //所以为什么不能直接 private一个 Liuedehua呢 //private LiuDeHua ldh=new LiuDeHua(); private Person ldh=new LiuDeHua(); //再设计一个方法生成代理对象 public Person getProxy(){ //使用Proxy.newProxyInstance(ClassLoader loader, Class [] interfaces, InvocationHandler h)返回某个对象的代理对象 //这次参数都是通过反射来获取到的 // newProxyInstance方法用来返回一个代理对象, // 这个方法总共有3个参数,ClassLoader loader用来指明生成代理对象使用哪个类装载器, // Class [] interfaces用来指明生成哪个对象的代理对象, // 通过接口指定,InvocationHandler h // 用来指明产生的这个代理对象要做什么事情。所以我们只需要调用newProxyInstance方法就可以得到某一个对象的代理对象了 return (Person) Proxy.newProxyInstance(LiuDeHuaProxy.class.getClassLoader(), ldh.getClass().getInterfaces(), new InvocationHandler() { //这个接口就是已定义了invoke这个方法,而new InvocationHandler就是针对这个接口的一个匿名实现类 //invoke有三个参数,proxy是把代理对象之间传递进来,method就是把代理对象当前调用的方法传递过来,args就是把方法参数传递过来 //代理还是反射的作用吧 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //这边如果是调用的是代理对象的sing的话 if(method.getName().equals("sing")){ System.out.println("我是他的经纪人,唱歌需要花十万"); //收完钱之后,就可以进行对应的操作了,对应的参数就是对应的代理对象和对应的名字 //这边比较好奇的,居然是ldh,也就是之前创建好的对象 return method.invoke(ldh,args); } if(method.getName().equals("dance")){ System.out.println("我是他的经纪人,跳舞需要花二十万"); //交完钱之后就可以调用了 return method.invoke(ldh,args); } //这个是我自己改的,也不知道对不对 return "别的活他不接"; } }); }}
最后的ProxyTest测试类:
package com.Kit.proxy;public class ProxyTest { public static void main(String[] args) { //首先创建一个代理,也就相当于是经纪人 LiuDeHuaProxy proxy=new LiuDeHuaProxy(); //然后通过代理获得一个对象,因为那边是person,所以这里也需要是person Person liuDeHua= proxy.getProxy(); //用来做对比 // LiuDeHua liuDeHua1=new LiuDeHua(); //那就是对应的操作了,这里就会发现,你调用直接的dance的时候,是会需要经过一个proxy的,可以和其他的对比一下 // liuDeHua.dance("yyy"); // System.out.println("**********"); //下面就是可以直接跳舞 // liuDeHua1.dance("yyy"); // System.out.println("**********"); //还有一个细节就是,把之前的代码换成下面这种 String result=liuDeHua.sing("xxx"); System.out.println(result); //就会发现 先是代理的出现,再是ldh的出现,最后才是 ldh的return }}
就此例子讲一下代理这个机制,也就是我自己的粗略理解:
重点就是看看这个代理的代码: 首先是创建了一个 对应的Person类:private Person ldh=new LiuDeHua();
因为是私有的,所以需要有一个公共方法来调用他:
也就是public Person getProxy()
这个方法就是返回了一个Person 类实例(这个实例由反射机制调用new出来的) 所以就需要重点说一下这个方法: Proxy.newProxyInstance 这个方法的参数分别是: 1.ClassLoader loader 指定的类装载器 2.Class[] interfaces 一组接口 3.InvocationHandler h 调用处理器生成动态实例 所以需要好好了解这几个参数存在的意义
对于第一个参数,其实差不多可以不用管他,知道用类名.class.getClassLoader() 第二个参数,是指定这个对象实现需要什么接口,并且一般来说就是一个接口就行了, 也就是对象.getClass().getInterfaces() 第三个参数,是最重要的,称之为调用处理器,在这里也就是调用invoke方法,所以有需要在里面把这个invoke方法进行编写:这里就很玄虚了,这几个参数是什么: Object proxy ,Method method ,Object[] args: 这个解释就很秒。转载地址:http://zsfen.baihongyu.com/