package com.bjsxt.proxy;
import java.lang.reflect.Method;
public interface InvocationHandler {
public void invoke(Object o, Method m);
}
2. Processing Method Implementation (Recording Method Runtime) TimeHandler.java
package com.bjsxt.proxy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TimeHandler implements InvocationHandler{
private Object target;
public TimeHandler(Object target) {
super();
this.target = target;
}
@Override
public void invoke(Object o, Method m) {
long start = System.currentTimeMillis();
System.out.println("starttime:" + start);
System.out.println(o.getClass().getName());
try {
m.invoke(target);
} catch (Exception e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("time:" + (end-start));
}
}
3. Proxy.java proxy generation class
package com.bjsxt.proxy;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
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 infce, InvocationHandler h) throws Exception { //JDK6 Complier API, CGLib, ASM
String methodStr = "";
String rt = "\r\n";
Method[] methods = infce.getMethods();
for(Method m : methods) {
methodStr += "@Override" + rt +
"public void " + m.getName() + "() {" + rt +
" try {" + rt +
" Method md = " + infce.getName() + ".class.getMethod(\"" + m.getName() + "\");" + rt +
" h.invoke(this, md);" + rt +
" }catch(Exception e) {e.printStackTrace();}" + rt +
"}";
}
String src =
"package com.bjsxt.proxy;" + rt +
"import java.lang.reflect.Method;" + rt +
"public class $Proxy1 implements " + infce.getName() + "{" + rt +
" public $Proxy1(InvocationHandler h) {" + rt +
" this.h = h;" + rt +
" }" + rt +
" com.bjsxt.proxy.InvocationHandler h;" + rt +
methodStr +
"}";
String fileName =
"d:/src/com/bjsxt/proxy/$Proxy1.java";
File f = new File(fileName);
FileWriter fw = new FileWriter(f);
fw.write(src);
fw.flush();
fw.close();
//use jdk compiler to compile
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
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:/" + "d:/src/")};
URLClassLoader ul = new URLClassLoader(urls);
Class c = ul.loadClass("com.bjsxt.proxy.$Proxy1");
System.out.println(c);
Constructor ctr = c.getConstructor(InvocationHandler.class);
Object m = ctr.newInstance(h);
return m;
}
}
4. Interface of proxy class Moveable.java
package com.bjsxt.proxy;
public interface Moveable {
void move();
}
5. Proxy class Tank.java
package com.bjsxt.proxy;
import java.util.Random;
public class Tank implements Moveable {
@Override
public void move() {
System.out.println("Tank Moving...");
try {
Thread.sleep(new Random().nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
6. Client Code
package com.bjsxt.proxy;
public class Client {
public static void main(String[] args) throws Exception {
Tank t = new Tank();
InvocationHandler h = new TimeHandler(t);
Moveable m = (Moveable)Proxy.newProxyInstance(Moveable.class, h);
m.move();
}
}
//It can realize arbitrary proxy for arbitrary object and arbitrary interface method.
In the Proxy.newProxyInstance(Moveable.class, h) method, the interface and processing method classes are introduced, and the method of the interface can be acquired and invoked by the interface class.
With the processing method class InvocationHandler, you can specify the processing method for the proxy object.
Generated proxy class code $Proxy1.java
package com.bjsxt.proxy;
import java.lang.reflect.Method;
public class $Proxy1 implements com.bjsxt.proxy.Moveable{
public $Proxy1(InvocationHandler h) {
this.h = h;
}
com.bjsxt.proxy.InvocationHandler h;
@Override
public void move() {
try {
Method md = com.bjsxt.proxy.Moveable.class.getMethod("move");
h.invoke(this, md);
}catch(Exception e) {e.printStackTrace();}
}}
More details can be referred to: Java-Horse Soldier Dynamic Agent Model