使用java的JavaCompiler模拟Proxy自动编译

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




你可能感兴趣的:(使用java的JavaCompiler模拟Proxy自动编译)