使用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;
}
}