Java_动态代理Proxy
来源:互联网 发布:核桃表妹淘宝店 编辑:程序博客网 时间:2024/05/02 14:24
1.动态代理概述
动态代理机制的出现,可以简单地指定类加载器对象和一组接口,便能动态地获得代理类,动态扩展功能。
Proxy有一点点小小的遗憾,仅支持 interface 代理,但可以使用CGLIB动态代理支持类!
2.代理模式
为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性。Java 动态代理机制以巧妙的方式近乎完美地实践了代理模式的设计理念。
3.动态代理机制
代理类构造函数只有一个,com.sun.proxy.$Proxy0(java.lang.reflect.InvocationHandler),方法和字段实现了接口的!
(1).通过实现 InvocationHandler 接口创建自己的调用处理器;
(2).通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
(3).通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
(4).通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
4.动态代理实例化
(1).简化型
通过newProxyInstance()方法,一步实例化动态代理类
Proxy.newProxyInstance(Collection.class.getClassLoader(), new Class[]{Collection.class}, MyInvocationHandler);/* * 实例化动态代理类,应该指定有那个类加载进行加载,一般加载器与实现接口一致 */
(2).复杂型
得到动态代理类的字节码文件,通过反射得到构造函数,并进行实例化
Class clazzProxy = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);Constructor con = clazzProxy.getConstructor(InvocationHandler.class);Collection collProxy = (Collection)con.newInstance(MyInvocationHandler);
5.InvocationHandler
代理类调用函数就会执行InvocationHandler的invoke() 方法,并向该函数传递三个参数信息proxyObject.add("sss"),从左向右依次为代理类实例对象,函数名,传递数组参数
public static void test() {Collection proxyObject = (Collection) Proxy.newProxyInstance(Collection.class.getClassLoader(),new Class[] { Collection.class }, new InvocationHandler() {public Object invoke(Object proxy, Method method,Object[] args) throws Throwable {return null;}});System.out.println(proxyObject.clear());//trueproxyObject.add("ss");//false java.lang.NullPointerException}
为什么clear()正确,而add却是错误的?
因为InvocationHandler的invoke() 方法执行结果的返回值为Object,当一个函数(add())的返回值为非void时,就会发生错误。解决办法是将该函数执行的结果返回!而clear返回值为null
正确解决办法
public static void test() {Collection proxyObject = (Collection) Proxy.newProxyInstance(Collection.class.getClassLoader(),new Class[] { Collection.class }, new InvocationHandler() {ArrayList<String> al = new ArrayList<String>();public Object invoke(Object proxy, Method method,Object[] args) throws Throwable {Object returnVal = method.invoke(al, args);return returnVal;//返回函数执行的结果}});proxyObject.add("sss");//true}
6.动态代理细节
(1).如果对同一组接口重复创建动态代理类,如果该Class字节码实例对象已经存在,则无需重新加载
Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);Class clazzProxy2 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);System.out.println(clazzProxy1 == clazzProxy2); // true
(2).所有动态代理类都是Proxy的子类
Class clazzProxy3 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);System.out.println(clazzProxy3.getSuperclass().getName());// java.lang.reflect.Proxy
- Java_动态代理Proxy
- JAVA_动态代理
- java_动态代理
- Java_浅谈动态代理
- Java Proxy动态代理
- 动态代理Proxy
- Java 动态代理 Proxy
- 动态代理(Proxy)
- 动态代理 Proxy InvocationHandler
- Proxy 动态代理。。。
- 动态代理proxy ,InvocationHandler
- Java动态代理Proxy
- 动态代理Proxy
- 动态代理proxy
- 动态代理 - proxy & InnovationHandler
- proxy动态代理
- 动态代理(Proxy)
- proxy 动态代理
- CXF 发布Web Service - JaxWsWebServicePublisherBeanPostProcessor
- 空间滚动字体和颜色修改教程
- 【CSDN浅墨】读书笔记1<Direct3D基础知识以及Direct3D初始化步骤>
- 打包生成CAB文件
- LWJGL教程--- 1.The Display
- Java_动态代理Proxy
- .Net版本&ckeditor_4.1.2+ckfinder+CuPlayerMiniV4+moPlayer&兼容ie7、ie8和火狐
- OpenCV2 && Qt4 chapter5: 形态学图像处理
- OpenGL中的函数gluPerspective简单理解
- 基于S3C2440的Linux-3.6.6移植——启动LOGO的修改
- 澳洲新人扫盲
- MYSQL登录错误:mysqladmin: connect to server at 'localhost' failed
- 分查找实现(Jon Bentley:90%程序员无法正确实现)
- Cocos2d-x 瓦片地图图层类CCTMXLayer