一、概述
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 }
三、運行結果

