本文可作为北京尚学堂 设计模式的学习笔记
在上一节 我们用谈到TankTimeProxy已经写死了 只能为一个类型的接口服务
在这一节 我们就试试解决这个问题 让代理类可以为任何类服务
package proxy; public class Proxy { public static Object newInstance(){ return null; } }我们假定有这个一个类 Proxy 它可以生成我们需要的代理类
package proxy; public class Client { public static void main(String[] args) { Imoveable m=(Imoveable) Proxy.newInstance(); t.move(); } }为了方便 我们暂时不动Proxy 先写一个测试类
package proxy.compiler.test; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; 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; import proxy.Imoveable; import proxy.Tank; public class Test { public static void main(String[] args) { String rt = "\r\n"; String src = "package proxy.compiler.test;" + rt + "import proxy.Imoveable;" + rt + "public class TankTimeProxy implements Imoveable {" + rt + " public TankTimeProxy(Imoveable t) {" + rt + " super();" + rt + " this.t = t;" + rt + " }" + rt + " Imoveable t;" + rt + " @Override" + rt + " public void move() {" + rt + " long start = System.currentTimeMillis();" + rt + " System.out.println(\"starttime:\" + start);" + rt + " t.move();" + rt + " long end = System.currentTimeMillis();" + rt + " System.out.println(\"end time:\" + end);" + rt + " System.out.println(\"expend time:\" + (end-start));" + rt + " }" + rt + "}"; } }对 我们把TankTimeProxy变成了一个字符串 再下面其实就是三步
String fileName = System.getProperty("user.dir") + "/src/proxy/compiler/test/TankTimeProxy.java"; File f = new File(fileName); FileWriter fw = new FileWriter(f); fw.write(src); fw.flush(); fw.close();此时在Eclipse左边的资源栏里可以看到 新生成了一个TankTimeProxy类
第二步
//compoler JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileManager = javaCompiler .getStandardFileManager(null, null, null); Iterable units = fileManager.getJavaFileObjects(fileName); CompilationTask task = javaCompiler.getTask(null, fileManager, null, null, null, units); task.call(); fileManager.close();这一步不懂得人就有很多了
StandardJavaFileManager getStandardFileManager( DiagnosticListener<? super JavaFileObject> diagnosticListener, Locale locale, Charset charset);这个DiagnosticListener 是出错后的监听类 咱们暂时不理会
CompilationTask getTask(Writer out, JavaFileManager fileManager, DiagnosticListener<? super JavaFileObject> diagnosticListener, Iterable<String> options, Iterable<String> classes, Iterable<? extends JavaFileObject> compilationUnits);这里面的参数 也很多 但我们还是不用管 把前面的两个变量赋进去 即可
其实说到这里 大家会觉得第二步都是些什么呀? 全部都是这个咱们不管 这个暂时不理会
说实话 对第二步 我也没有仔细的研究过 能用即可 我认为 这部分的相关知识 要想研究 问Google
不过我真的不认为 这些略过的东西很重要
继续看第三步
到这里 class文件我们也有了
再下面就是利用反射的知识获得类
// load into memory and create an instance URL[] urls = new URL[] { new URL("file:/" + System.getProperty("user.dir") + "/src") }; URLClassLoader ul = new URLClassLoader(urls); Class c = ul.loadClass("proxy.compiler.test.TankTimeProxy"); Constructor cons= c.getConstructor(Imoveable.class); Imoveable m=(Imoveable)cons.newInstance(new Tank()); m.move();我们用UrlClassLoader从src底下加载进来类
package proxy; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.net.URLClassLoader; import javax.tools.JavaCompiler; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; import javax.tools.JavaCompiler.CompilationTask; public class Proxy { public static Object newInstance() throws IOException, ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{ String rt = "\r\n"; String src = "package proxy.compiler.test;" + rt + "import proxy.Imoveable;" + rt + "public class TankTimeProxy implements Imoveable {" + rt + " public TankTimeProxy(Imoveable t) {" + rt + " super();" + rt + " this.t = t;" + rt + " }" + rt + " Imoveable t;" + rt + " @Override" + rt + " public void move() {" + rt + " long start = System.currentTimeMillis();" + rt + " System.out.println(\"starttime:\" + start);" + rt + " t.move();" + rt + " long end = System.currentTimeMillis();" + rt + " System.out.println(\"end time:\" + end);" + rt + " System.out.println(\"expend time:\" + (end-start));" + rt + " }" + rt + "}"; String fileName = System.getProperty("user.dir") + "/src/proxy/compiler/test/TankTimeProxy.java"; File f = new File(fileName); FileWriter fw = new FileWriter(f); fw.write(src); fw.flush(); fw.close(); //compoler JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileManager = javaCompiler .getStandardFileManager(null, null, null); Iterable units = fileManager.getJavaFileObjects(fileName); CompilationTask task = javaCompiler.getTask(null, fileManager, null, null, null, units); task.call(); fileManager.close(); // load into memory and create an instance URL[] urls = new URL[] { new URL("file:/" + System.getProperty("user.dir") + "/src") }; URLClassLoader ul = new URLClassLoader(urls); Class c = ul.loadClass("proxy.compiler.test.TankTimeProxy"); Constructor cons= c.getConstructor(Imoveable.class); Imoveable m=(Imoveable)cons.newInstance(new Tank()); return m; } }
package proxy; import java.io.IOException; import java.lang.reflect.InvocationTargetException; public class Client { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException { Imoveable m=(Imoveable) Proxy.newInstance(); m.move(); } }
@Override public void move() { // TODO Auto-generated method stub System.out.println("i can move..."); try { Thread.sleep(new Random().nextInt(10000)); } catch (InterruptedException e) { e.printStackTrace(); } }