简单模拟java动态动态代理机制的底层实现原理
在网上学习了马士兵老师的设计模式视屏,过程中也有认真的做相应的笔记。在次分享我的一些
成果,方便大家的进一步学习。
1、接口
1 public interface Moveable { 2 void move(); 3 }
2、被代理的对象
1 public class Tank implements Moveable { 2 3 @Override 4 public void move() { 5 6 System.out.println("Tank Moving..."); 7 try { 8 Thread.sleep(new Random().nextInt(10000)); 9 } catch (InterruptedException e) { 10 e.printStackTrace(); 11 } 12 13 } 14 15 }
3、测试主类
1 public class Test { 2 public static void main(String[] args) throws Exception{ 3 String rt = "\r\n"; 4 5 //代理类的字符串代码 6 String src = 7 "public class TankTimeProxy implements Moveable {"+rt+ 8 " Moveable t;"+rt+ 9 10 " public TankTimeProxy(Moveable t) {"+rt+ 11 " this.t = t;"+rt+ 12 " }"+rt+ 13 14 " @Override"+rt+ 15 " public void move() {"+rt+ 16 " long start = System.currentTimeMillis();"+rt+ 17 " System.out.println(\"start time is \"+start);"+rt+ 18 " t.move();"+rt+ 19 " long end = System.currentTimeMillis();"+rt+ 20 " System.out.println(\"end time is \"+end);"+rt+ 21 " System.out.println(\"time is \"+(end - start));"+rt+ 22 " }"+rt+ 23 "}"; 24 25 //将字符串写入java文件******************************************************************************** 26 String fileName = System.getProperty("user.dir")+"/src/TankTimeProxy.java";//放置在(根目录+文件名)下 27 File f = new File(fileName); 28 FileWriter fw = new FileWriter(f); 29 //写入内容 30 fw.write(src); 31 fw.flush(); 32 fw.close(); 33 34 //进行编译******************************************************************************************** 35 //首先获得编译器 36 //compiler 为java编译器 即javac 37 //获得编译器对象 38 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 39 40 //参数含义 (编译诊断,locale,charset) 41 //管理动态生成的文件的StandardJavaFileManager对象 42 StandardJavaFileManager fileManager = compiler.getStandardFileManager(null,null,null);//默认值 43 44 //根据参数获取多个java文件 返回java文件对象集 45 Iterable units = fileManager.getJavaFileObjects(fileName); 46 47 //“编译任务”对象 48 JavaCompiler.CompilationTask task = compiler.getTask(null,fileManager,null,null,null,units); 49 task.call();//调用 50 fileManager.close(); 51 52 //************以上过程获得了java文件源码,编译java文件生成了相对应的class文件**************** 53 54 //***************以下过程为将class文件加载至内存,生成新对象***************************** 55 //Class.load() 是加载path路径的class文件 56 //URLClassLoader是将硬盘中的class文件加载进入 57 58 //通过Url引入本地文件 59 URL[] urls = new URL[]{new URL("file:/"+System.getProperty("user.dir")+"/out/production/proxy")}; //访问本地class文件,这里我用的是IntellijIDEA,默认 生成的class文件的目录在 /out/production/ 下 60 61 62 //去指定路径寻找class文件 63 URLClassLoader urlClassLoader = new URLClassLoader(urls); 64 65 Class c = urlClassLoader.loadClass("TankTimeProxy"); 66 67 System.out.println(c); 68 69 //执行 70 //c.newInstance(); 是调用空的构造方法 71 72 //获得构造方法 73 //根据java虚拟机,每一个构造方法也相当于一个对象 74 Constructor constructor = c.getConstructor(Moveable.class); 75 76 //产生新对象 77 Moveable m = (Moveable) constructor.newInstance(new Tank()); //new Tank()为构造方法的参数 即被代理对象 78 79 m.move(); 80 81 } 82 } 83 84
4、执行结果