一、概述
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
package proxy; public interface Movable {
public void move();
}
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
package proxy; import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLClassLoader; import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider; public class Proxy { public static Object newProxyInstance() throws Exception {
String rt = "\n\r"; //动态代理文件的源码
String str =
"package proxy;" + rt + "public class TankTimeProxy implements Movable {"+rt+ "private Movable m;" + rt + "public TankTimeProxy(Movable m) {" + rt +
"this.m = m;" + rt +
"}" + rt + "@Override" + rt +
"public void move() {" + rt +
"System.out.println(\"Time Proxy start...........\");" + rt +
"long start = System.currentTimeMillis();" + rt +
"m.move();" + rt +
"long end = System.currentTimeMillis();" + rt +
"System.out.println(\"花费时间:\"+(end - start));" + rt +
"System.out.println(\"Time Proxy end...........\");" + rt +
"}" + rt + "}" ; //把源码写到java文件里
File file = new File(System.getProperty("user.dir")+"/src/proxy/TankTimeProxy.java");
FileWriter fw = new FileWriter(file);
fw.write(str);
fw.flush();
fw.close(); //编译源码,生成class,注意编译环境要换成jdk才有compiler,单纯的jre没有compiler,会空指针错误
JavaCompiler jc = ToolProvider.getSystemJavaCompiler(); //文件管事器
StandardJavaFileManager fileMgr = jc.getStandardFileManager(null, null, null); //编译单元
Iterable units = fileMgr.getJavaFileObjects(file); //编译任务
CompilationTask t = jc.getTask(null, fileMgr, null, null, null, units); //编译
t.call();
fileMgr.close(); //把类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"); //生成实例
//return c.newInstance(); //c.newInstance()会调用无参数的Construtor,若类没有无参的Constructor时会出错
Constructor ctr = c.getConstructor(Movable.class);
return ctr.newInstance(new Tank());
}
}
4.Client.java
package proxy; import java.io.IOException; import org.junit.Test; public class Client { @Test
public void testProxy() throws Exception{ Movable m = (Movable)Proxy.newProxyInstance();
m.move(); }
}
三、运行结果