博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java代理模式实例讲解
阅读量:7118 次
发布时间:2019-06-28

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

下面这个是设计模式课上的例子:

1 import java.lang.reflect.InvocationHandler; 2 import java.lang.reflect.Method; 3 import java.lang.reflect.Proxy; 4 import java.util.List; 5 import java.util.Vector; 6  7  8 public class VectorProxy implements InvocationHandler { 9 10     private Object targetObj;11     12     public Object getObject(){13         return targetObj;14     }15     16     public VectorProxy(Object Obj){17         targetObj = Obj;18     }19     20     public static Object factorary(Object Obj){21         22         Class cla = Obj.getClass();23         Object proxy = Proxy.newProxyInstance(cla.getClassLoader(), cla.getInterfaces(), new VectorProxy(Obj));24         return proxy;25     }26 27     public Object invoke(Object proxy, Method method, Object[] args)28             throws Throwable {29         System.out.println("befor invoke   "+method.getName());30         if(args!=null){31             for(Object o:args){32                 System.out.println(o.toString());33             }34         }35         36         Object tarObj = ((VectorProxy)(Proxy.getInvocationHandler(proxy))).getObject();37         38         System.out.println(tarObj==targetObj);39         40         Object resultObj = method.invoke(targetObj,args);41         42         return resultObj;43     }44     45     public static void main(String args[]){46         List v = null;47         v = (List)factorary(new Vector(10));48         v.add("NEW");49         System.out.println(v.get(0));50     }51     52 }

结果:

befor invoke   addNEWtruebefor invoke   get0trueNEW

我通过这个例子来讲一下我对动态代理的理解。

从main函数入口开始。当我执行了v = (List)factorary(new Vector(10));的时候,这时所做的操作有21~24,我们看23行,这个Proxy.newProxyInstance函数会生成一个代理的实例,但是生成谁的实例呢?我们来看一下这个函数的原型:public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

它生成的是接口InvocationHandler这个接口的实例,在本例中中类VectorProxy实现了这个接口且在23行,传入将这个类传入进去了。这个函数返回实现了被代理类所实现的所有接口的Object对象,即动态代理,需要强制转型。代码中红色标注部分就是因为

Vector对应的接口是List,这里的返回值必须是接口。VectorProxy 中的子类必须是implements这个接口的类。

这里可以再看一下47行,对应于这句话(List)就是强制类型转换,类成员变量targetObj就是被代理类,这里是Vector,实现的所有接口则就是Vector的各种操作例如get,add这些。在47行,这个实现了所有Vector接口的Vector对象被赋值给了v。下面就是接口InvocationHandler里的这个invoke函数了,这个函数是自动调用的,29~39都是可以去掉的,有用的只是40行的这个。然后至于40行的这个详细内容可以去我的上篇博客  中去看,这里不再赘述。

接下来看一下29~39行的这些对应的输出。这些输出的原理看完 之后都可以看懂,我就来讲一下37行的这句,先看一下Proxy这个类的成员变量:

 

如果你在factorary中加上一句 System.out.println("proxy的类型"+proxy.getClass().getName());   然后对应的输出就是 proxy 的类型 $Proxy0,在 Proxy 的类的定义中我们发现它有一个 proxyClassNamePrefix 的东西,这个前缀加上0就是我们这个生成的代理的proxy,所以37行的那个 Object tarObj = ((VectorProxy)(Proxy.getInvocationHandler(proxy))).getObject(); 这儿proxy就是一个标号,然后其实就是那个v就是通过这个标号去进行add,get操作其实v(也就是proxy,接下来用v)并没有实现所有的方法,它只是通过invoke把v的这些操作通过java底层第调用仍然由被代理对象本身的函数去处理了,v所指代的并不是一个新的和之前的targetObj不一样的类,它只是一个指向了那个类的高级标识符,可以对类进行操作而已。合理猜测:Proxy中的两个map成员变量应该是存储多个代理类用的用来存放v(proxy)用的。讲到了这儿已经没有什么可再说的啦。

转载于:https://www.cnblogs.com/chaiwentao/p/4417154.html

你可能感兴趣的文章
聊聊Elasticsearch RestClient的RequestLogger
查看>>
iOS视频采集实战(AVCaptureSession)
查看>>
使用java9的uuid生成方式,让uuid生成速度提升一个档次
查看>>
SpringData JDBC
查看>>
Vue源码阅读一:说说vue.nextTick实现
查看>>
《iOS面试之道》算法基础学习(上)
查看>>
js定义到执行(转)
查看>>
Google陆续收购技能机器人技术公司——智能机器人未来是否会发热?
查看>>
前端埋点方法解析及优缺点分析
查看>>
笔记:Gitlab-CI部署流程
查看>>
面向对象-day02
查看>>
如果要学习web前端,需要学习什么
查看>>
《编写高质量代码:改善Java程序的151个建议》笔记
查看>>
LeetCode每日一题: 搜索插入位置(No.35)
查看>>
利用装饰器实现mock和api的局部分离切换
查看>>
-[UIView hitTest:withEvent:] 方法总结
查看>>
springboot
查看>>
ios设计规范(下)
查看>>
Git-github 的基本应用
查看>>
前端基础8:HTML5新增标签及CSS3新属性 viewport 动画
查看>>