JDK动态代理实现原理(简析加转载)
2016-04-29 23:28
447 查看
这里探讨JDK动态代理是如何实现的。JDK生成动态代理的语法如下,参考JDK动态代理示例:
关键是看
1、关键是生成代理类的字节码文件(生成后放在磁盘上),然后通过类加载器加载这个字节码文件。
这个代理类要implements参数中传入的所有接口,并实现其中的方法。
2、关于如何实现接口中的方法,其实只要拼一个相应方法的方法体,然后调用参数中DynamicProxyHandler的invoke方法,使用反射机制。
MyProxy的代码如下,不确定准不准确,会继续研究:
参考:
http://www.itzhai.com/java-dong-tai-dai-li-zhi-jdk-dong-tai-dai-li-he-cglib-dong-tai-dai-li-mian-xiang-qie-mian-bian-cheng-aop-yuan-li.html#read-more
http://rejoy.iteye.com/blog/1627405
http://blog.csdn.net/zhangerqing/article/details/42504281
Interface proxy = (Interface) Proxy.newProxyInstance(Interface.class.getClassLoader(), new Class[]{Interface.class}, new DynamicProxyHandler(real));
关键是看
newProxyInstance方法是如何工作的,再探讨这个方法之前,先分析一篇看到的日志。这个日志大体实现了一个自定义的Proxy类,称为MyProxy类。代码会在后面给出。这里分析几个要点:
1、关键是生成代理类的字节码文件(生成后放在磁盘上),然后通过类加载器加载这个字节码文件。
这个代理类要implements参数中传入的所有接口,并实现其中的方法。
2、关于如何实现接口中的方法,其实只要拼一个相应方法的方法体,然后调用参数中DynamicProxyHandler的invoke方法,使用反射机制。
MyProxy的代码如下,不确定准不准确,会继续研究:
package com.itzhai.javanote.proxy; import java.io.File; import java.io.FileWriter; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.Arrays; import javax.tools.JavaCompiler; import javax.tools.JavaCompiler.CompilationTask; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; public class MyProxy { public static Object newProxyInstance(Class interfaces,MyInvocationHandler handler) throws Exception{ String r = "\n"; Method[] methods = interfaces.getMethods(); StringBuffer sb = new StringBuffer(""); //生成需要代理的接口中的所有方法 的代码,通过调用MyInvocationHandler的invoke方法实现真实对象方法的调用 for(int i =0;i<methods.length;i++){ sb.append(" public void "+methods[i].getName()+"() {"+ r + " try{ "+ r + " Method md = "+interfaces.getName()+".class.getMethod(\""+methods[i].getName()+"\");"+ r + " handler.invoke( md,new Object[]{});"+ r + " }catch(Exception e){e.printStackTrace();}"+ r + " }"+r + r ); } // 生成完整的类代码 String src = "package com.itzhai.javanote.proxy;"+ r + r + "import java.lang.reflect.*;"+ r + r + "public class Proxy$1 implements "+interfaces.getName() +"{"+ r + " private com.itzhai.javanote.proxy.MyInvocationHandler handler;"+ r + " public Proxy$1("+handler.getClass().getName() +" handler){"+ r + " this.handler = handler;"+ r + " }"+ r + r + sb.toString() + "}" +r; // 输出Java文件 String dir = System.getProperty("user.dir")+"/src/com/itzhai/javanote/proxy/"; FileWriter writer = new FileWriter(new File(dir+"Proxy$1.java")); writer.write(src); writer.flush(); writer.close(); // 编译动态代理类 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null); Iterable<? extends JavaFileObject> units = fileMgr.getJavaFileObjects(dir+"Proxy$1.java"); Iterable<String> options = Arrays.asList("-d", System.getProperty("user.dir") + "/bin/"); CompilationTask t = compiler.getTask(null, fileMgr, null, options, null, units); t.call(); fileMgr.close(); // 加载动态代理类,并返回动态代理类的实例 URL[] urls = new URL[]{new URL("file:/"+dir)}; URLClassLoader loader = new URLClassLoader(urls); Class c = loader.loadClass("com.itzhai.javanote.proxy.Proxy$1"); Constructor ctr = c.getConstructor(handler.getClass()); return ctr.newInstance(handler); } }
参考:
http://www.itzhai.com/java-dong-tai-dai-li-zhi-jdk-dong-tai-dai-li-he-cglib-dong-tai-dai-li-mian-xiang-qie-mian-bian-cheng-aop-yuan-li.html#read-more
http://rejoy.iteye.com/blog/1627405
http://blog.csdn.net/zhangerqing/article/details/42504281
相关文章推荐
- java中HashMap与Hashtable的区别
- Java mail API学习
- java的数据类型
- Java语言中,求数组中的最大值
- MyEclipse2014 如何破解
- serlet和JSP之间值传递,一些基础的java,
- java并发之ConcurrentHashMap
- webservice与spring整合发布后台服务
- spring 配置文件详解-个人学习笔记
- Eclipse自动生成 get/set
- 如何使用java语言遍历数组
- 关于Java中“+”加运算符和“<<”向前移位运算符混合使用时出现的错误
- 20145337 《Java程序设计》第九周学习总结
- java带界面数据库连接简易Atm项目
- SpringMVC 使用验证框架 Bean Validation(下)
- java中常用的字符串的截取方法1
- javaWeb基础核心之一Servlet
- JAVA基础三——安卓开发的基础
- Java内存区域与内存溢出异常
- Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)