java代理及动态代理
来源:互联网 发布:造诣软件 编辑:程序博客网 时间:2024/04/29 12:46
代理在java技术中起着很重要的作用,Spring的aop及各种开源框架都使用了代理的技术。
代理一般分为:静态代理与动态代理。
一、 静态代理,一般分为 类继承代理与对象组合代理。 类继承就是继承超类获得超类的功能。
在应用中,一般用组合代理。
如下图:
二、在java应用中,动态代理应用更广泛,可以说这是java语言的特性。
public class SetProxyFactory {@SuppressWarnings("unchecked")public static <T> T getProxy(final T obj) {// 类加载器、类的接口、一个InvocationHandler实现return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {System.out.println("Start....");return method.invoke(obj, args);}});}public static void main(String[] agrs) throws ClassNotFoundException {Set<String> set = new HashSet<String>();// 创建一个类Set<String> proxySet = SetProxyFactory.getProxy(set);// 有类生成一个代理对象System.out.println(Proxy.getInvocationHandler(proxySet));System.out.println(proxySet.size());}}
- 动态代理主要涉及到 Proxy类与InvocationHandler类。
- Proxy有一个 public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)返回值是一个由JVM动态生成的类所实例化的对象,可以认为InvocationHandler 是这个类的变量属性。
- loader是类加载器
- interfaces 是接口列表
- InvocationHandler 是一个InvocationHandler 的实例。
- InvocationHandler有一个接口: public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;此接口可以认为是回调函数,也就是代理的类的对象 被访问时候,就会触发它所绑定的 InvocationHandler 的invoke方法。传来的差数有代理类,方法,差数列表。在invoke方法一般有method.invoke(obj, args)调用,obj真正的实例。
- Proxy有一个 public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)返回值是一个由JVM动态生成的类所实例化的对象,可以认为InvocationHandler 是这个类的变量属性。
- 动态关键类还是Proxy类的newProxyInstance方法,我们可以进入源码一看究竟。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)throws IllegalArgumentException {if (h == null) { throw new NullPointerException();}/* * Look up or generate the designated proxy class. */Class cl = getProxyClass(loader, interfaces);//关键是创建代理类/* * Invoke its constructor with the designated invocation handler. */try { Constructor cons = cl.getConstructor(constructorParams); return (Object) cons.newInstance(new Object[] { h });//InvocationHandler是作为一个实例变量传入代理类中。} catch (NoSuchMethodException e) { throw new InternalError(e.toString());} catch (IllegalAccessException e) { throw new InternalError(e.toString());} catch (InstantiationException e) { throw new InternalError(e.toString());} catch (InvocationTargetException e) { throw new InternalError(e.toString());} }
- 关键还是 Class cl = getProxyClass(loader, interfaces); getProxyClass方法,该方法的差数是 ClassLoader 与 Classinterfaces。此方法中主要分为:
- 检查 ,一般有:接口数目不能大于65535,禁止非接口,禁止有重复的接口等。
- 缓存并复用。
- 定义名称
long num;synchronized (nextUniqueNumberLock) { num = nextUniqueNumber++;}String proxyName = proxyPkg + proxyClassNamePrefix + num;
- 创建代理类。代码如下
/* * Generate the specified proxy class. */byte[] proxyClassFile =ProxyGenerator.generateProxyClass( proxyName, interfaces); 主要是此方法,生成了 字节码。 如果要看,建议使用openjdk及看看jvm字节码try { proxyClass = defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);
- 最后调用 defineClass0 根据字节码生成代理类。
- 我们可以看下动态代理的类图
- 在上图中$ProxyN是代理类。继承Proxy类。在实现了接口。$ProxyN其实跟User是没有关系的。调用是通过AInvocationHandler来实现的。
三、其它
- 为什么使用代理:主要的目的是为了对目标类,进行精确的控制。打打日志。
- 为什么用动态代理不用静态代理:用静态代理,如果目标方法改变则需要修改代理类,很不方便。动态代理能避免这个。
- 我们要注意什么?针对接口代理,不能针对类进行动态代理这个也有点遗憾。许多的框架都使用动态代理,debug程序的时候一定要注意。
四、参考资料
- Java 动态代理机制分析及扩展:http://www.ibm.com/developerworks/cn/java/j-lo-proxy1
- ProxyAPI:http://dlc.sun.com.edgesuite.net/jdk/jdk-api-localizations/jdk-api-zh-cn/publish/1.6.0/html/zh_CN/api/java/lang/reflect/Proxy.html
五、版权声明
- 此文可以自由转载,请保留 著作者相关信息。
- 原文地址:http://blog.csdn.net/bxyz1203/article/details/6071310
- 作者:就职于 阿里巴巴 封神
- java代理及动态代理
- java代理模式及动态代理类
- 代理模式及Java动态代理
- Java代理模式及动态代理
- Java代理模式及动态代理
- 代理模式及Java实现动态代理
- Java 中的代理模式及动态代理
- Java 中的代理模式及动态代理
- 代理模式及Java实现动态代理
- 代理及动态代理
- 代理及动态代理
- Java代理机制及动态代理和CGLIB代理详解
- Java 代理,动态代理
- Java动态代理及原理
- java反射及动态代理
- Java注解及动态代理
- Java代理(jdk静态代理、动态代理和cglib动态代理)实例及总结
- 代理模式及动态代理
- C++ 笔试面试题链接
- Jlink 在S3C2440上的使用
- 一个人的寂寞
- dba_sql跟踪查询
- 串口通信CSerialPort类WriteToPort不能连续发送的问题
- java代理及动态代理
- hibernate优化
- 46家公司的笔试题,拿去练练手吧
- RS232串口通信详解(引脚定义,电气特性,传输格式,接收过程,单片机晶振,RS485,RS422)
- objective-c - delegate
- VC++ 判断文件夹是否存在,若不存在,创建新文件夹
- 多线程 相关知识
- 在线为Eclipse安装SVN插件
- VisionMobile:移动平台生态系统冲突报告(一)关键点提要