Java-马士兵设计模式学习笔记-代理模式-动态代理 调用Proxy.newProxyInstance()
一、概述
1.目标:不自己写代理类,利用Proxy.newProxyInstance()动态生成
2.用到的知识点:
(1)//编译源码,生成class,注意编译环境要换成jdk才有compiler,单纯的jre没有compiler,会空指针错误
JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
(2)//文件管事器
StandardJavaFileManager fileMgr = jc.getStandardFileManager(null, null, null);
(3)//编译单元
Iterable units = fileMgr.getJavaFileObjects(file);
(4)//编译任务
CompilationTask t = jc.getTask(null, fileMgr, null, null, null, units);
(5)//编译
t.call();
(6)//把类load到内存里
URL[] urls = new URL[] {new URL("file:/"+System.getProperty("user.dir")+"/src/proxy/TankTimeProxy.class")};
URLClassLoader uc = new URLClassLoader(urls);
Class c = uc.loadClass("proxy.TankTimeProxy");
(7)//生成实例
//return c.newInstance(); //c.newInstance()会调用无参数的Construtor,若类没有无参的Constructor时会出错
Constructor ctr = c.getConstructor(Movable.class);
return ctr.newInstance(new Tank());
二、代码
1.Movable.java
2.Tank.java
3.Proxy.java
4.Client.java
1.Movable.java
1 package proxy; 2 3 public interface Movable { 4 public void move(); 5 }
2.Tank.java
package proxy; import java.util.Random; public class Tank implements Movable { @Override public void move() { System.out.println("Tank moving......."); try { Thread.sleep(new Random().nextInt(2000)); } catch (InterruptedException e) { e.printStackTrace(); } } }
3.Proxy.java
1 package proxy; 2 3 import java.io.File; 4 import java.io.FileWriter; 5 import java.lang.reflect.Constructor; 6 import java.net.URL; 7 import java.net.URLClassLoader; 8 9 import javax.tools.JavaCompiler; 10 import javax.tools.JavaCompiler.CompilationTask; 11 import javax.tools.StandardJavaFileManager; 12 import javax.tools.ToolProvider; 13 14 public class Proxy { 15 16 public static Object newProxyInstance() throws Exception { 17 String rt = "\n\r"; 18 19 //动态代理文件的源码 20 String str = 21 "package proxy;" + rt + 22 23 "public class TankTimeProxy implements Movable {"+rt+ 24 25 "private Movable m;" + rt + 26 27 "public TankTimeProxy(Movable m) {" + rt + 28 "this.m = m;" + rt + 29 "}" + rt + 30 31 "@Override" + rt + 32 "public void move() {" + rt + 33 "System.out.println(\"Time Proxy start...........\");" + rt + 34 "long start = System.currentTimeMillis();" + rt + 35 "m.move();" + rt + 36 "long end = System.currentTimeMillis();" + rt + 37 "System.out.println(\"花费时间:\"+(end - start));" + rt + 38 "System.out.println(\"Time Proxy end...........\");" + rt + 39 "}" + rt + 40 41 "}" ; 42 43 //把源码写到java文件里 44 File file = new File(System.getProperty("user.dir")+"/src/proxy/TankTimeProxy.java"); 45 FileWriter fw = new FileWriter(file); 46 fw.write(str); 47 fw.flush(); 48 fw.close(); 49 50 //编译源码,生成class,注意编译环境要换成jdk才有compiler,单纯的jre没有compiler,会空指针错误 51 JavaCompiler jc = ToolProvider.getSystemJavaCompiler(); 52 53 //文件管事器 54 StandardJavaFileManager fileMgr = jc.getStandardFileManager(null, null, null); 55 56 //编译单元 57 Iterable units = fileMgr.getJavaFileObjects(file); 58 59 //编译任务 60 CompilationTask t = jc.getTask(null, fileMgr, null, null, null, units); 61 62 //编译 63 t.call(); 64 fileMgr.close(); 65 66 //把类load到内存里 67 URL[] urls = new URL[] {new URL("file:/"+System.getProperty("user.dir")+"/src/proxy/TankTimeProxy.class")}; 68 URLClassLoader uc = new URLClassLoader(urls); 69 Class c = uc.loadClass("proxy.TankTimeProxy"); 70 71 //生成实例 72 //return c.newInstance(); //c.newInstance()会调用无参数的Construtor,若类没有无参的Constructor时会出错 73 Constructor ctr = c.getConstructor(Movable.class); 74 return ctr.newInstance(new Tank()); 75 } 76 }
4.Client.java
1 package proxy; 2 3 import java.io.IOException; 4 5 import org.junit.Test; 6 7 public class Client { 8 9 @Test 10 public void testProxy() throws Exception{ 11 12 Movable m = (Movable)Proxy.newProxyInstance(); 13 m.move(); 14 15 } 16 }
三、运行结果