使用java的jdk6的JavaCompiler进行自动编译,将一段字符串编译为class文件、并且存到内存中,可以对任意的对象实现代理
比方说有一个对象Tank要做代理,就先创建一个TimeHandler来实现InvocationHandler,该TimeHadler中保存了一个该对象的引用
如
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class TimeHandler implements InvocationHandler{ Object target; public TimeHandler(Object target) { this.target = target; } public void invoke(Object o,Method m) {//是对哪个对象调用Method m,m为二进制代码,前面的o指的是代理的那个 long start = System.currentTimeMillis(); try { m.invoke(target);//调用target这个对象的m方法。第二个指的是想方法中传的参数,本例为空 } catch (Exception e) { e.printStackTrace(); } long end = System.currentTimeMillis(); System.out.println("time:"+(end-start)); } }客户端调用:
public class Client { public static void main(String[] args) throws Exception { Tank t = new Tank(); InvocationHandler ich = new TimeHandler(t); Moveable m = (Moveable)Proxy.newProxyInstance(Moveable.class,ich); m.move(); } }
package com.lxp.proxy; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Constructor; 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 newProxyInstance(Class inface,InvocationHandler h) throws Exception { String rt = "\r\n"; String src = "package com.lxp.proxy;"+rt+ "public class TankTimeProxy implements " +inface.getName()+"{"+rt+ " Moveable t;"+rt+ " TankTimeProxy(Moveable t) {"+rt+ " this.t = t;"+rt+ " }"+rt+ " public void move() {"+rt+ " long start = System.currentTimeMillis();"+rt+ " t.move();"+rt+ " long end = System.currentTimeMillis();"+rt+ " System.out.println(\"time:\"+(end-start));"+rt+ " }"+rt+ "}"; String fileName = System.getProperty("user.dir")+"/src/com/lxp/proxy/TankTimeProxy.java"; File f = new File(fileName); FileWriter fw = new FileWriter(f); fw.write(src); fw.flush(); fw.close(); //使用java自带的编译工具JavaCompiler对一段字符串进行编译 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();//拿到系统编译器javac // System.out.println(compiler.getClass().getName()); StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null); Iterable units = fileMgr.getJavaFileObjects(fileName); CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units); t.call();//开始编译 fileMgr.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("com.lxp.proxy.TankTimeProxy");//生成class到内存 // System.out.println(c); Constructor ctr = c.getConstructor(Moveable.class);//寻找一个有参数的并且参数类型是Moveable的构造方法 Moveable m = (Moveable) ctr.newInstance(new Tank());//构造方法中有参数,所以穿一个值过去 m.move(); return null; } }