模拟实现JDK动态代理Proxy
- 可以对任意的对象、任意的接口方法实现任意的代理
Handler接口
package cn.chen.proxy.compiler;
import java.lang.reflect.Method;
public interface InvocationHander {
void invoke(Object o,Method method);
}
代理类实现Handler接口,编入自己的逻辑
package cn.chen.proxy.compiler;
import java.lang.reflect.Method;
public class TimeHander implements InvocationHander {
private Object target;
public TimeHander(Object target) {
this.target = target;
}
@Override
public void invoke(Object o,Method method) {
long start = System.currentTimeMillis();
System.out.println("开始:" + start);
System.out.println(o.getClass().getName());
try {
method.invoke(target,new Object[]{});
} catch (Exception e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("运行:" + (start - end));
}
}
package cn.chen.proxy.compiler.test;
import cn.chen.proxy.compiler.InvocationHander;
import java.lang.reflect.Method;
public class TransacationHandler implements InvocationHander{
private Object target;
public TransacationHandler(Object target) {
this.target = target;
}
@Override
public void invoke(Object o, Method method) {
System.out.println("Transaction start");
try {
method.invoke(target);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Transaction commit");
}
}
Proxy产生新的代理类
JDK6的编译api
package cn.chen.proxy;
import cn.chen.proxy.compiler.InvocationHander;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
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;
public class Proxy {
/**
* 产生新的代理类
* @return
*/
public static Object newProxyInstance(Class infce, InvocationHander h) throws Exception {
String methodStr = "";
String rt = "\n";
Method[] methods = infce.getMethods();
// for(Method method : methods){
// methodStr += "@Override" + rt +
// "public void " + method.getName() + "()" +"{"+rt +
// " long start = System.currentTimeMillis();" + rt +
// " System.out.println(\"开始:\" + start);" + rt +
// " tank."+method.getName()+"();\n" +
// " long end = System.currentTimeMillis();\n" +
// " System.out.println(\"运行:\" + (start - end));\n" +
// "}";
// }
for(Method method : methods){
methodStr += "@Override" + rt +
"public void " + method.getName() + "()" +"{"+rt +
" try{" + rt +
" Method method = "+ infce.getName() + ".class.getMethod(\""+ method.getName()+"\");" + rt +
" h.invoke(this,method);" + rt +
" }catch(Exception e){e.printStackTrace();}" +
"}";
}
String src = "package cn.chen.proxy.compiler;\n" +
"import cn.chen.proxy.Moveable;\n" +
"import java.lang.reflect.Method;\n" +
"public class $Proxy1 implements " + infce.getName() +" {\n" +
" public $Proxy1(InvocationHander h) {\n" +
" this.h = h;" + rt +
" }" + rt +
" cn.chen.proxy.compiler.InvocationHander h;"+ rt+
methodStr + rt+
"}";
// /Users/chenxiaokang/Documents/IDEAProject/mianshi
// System.out.println(System.getProperty("user.dir"));
String fileName = System.getProperty("user.dir") + "/src/main/java/cn/chen/proxy/compiler/$Proxy1.java";
File f = new File(fileName);
FileWriter fw = new FileWriter(f);
fw.write(src);
fw.flush();
fw.close();
// 编译
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
// com.sun.tools.javac.api.JavacTool
// System.out.println(compiler.getClass().getName());
StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null,null,null);
Iterable units = fileMgr.getJavaFileObjects(fileName);
JavaCompiler.CompilationTask task = compiler.getTask(null, fileMgr, null, null, null,units);
task.call();
fileMgr.close();
//load into memory and create an instance
URL[] urls = new URL[]{new URL("file:/" + System.getProperty("user.dir") + "/src/main/java")};
URLClassLoader ul = new URLClassLoader(urls);
Class c = ul.loadClass("cn.chen.proxy.compiler.$Proxy1");
System.out.println(c);
Constructor constructor = c.getConstructor(InvocationHander.class);
Object m = constructor.newInstance(h);
return m;
}
}
中间生成的代理代码
package cn.chen.proxy.compiler;
import cn.chen.proxy.Moveable;
import java.lang.reflect.Method;
public class $Proxy1 implements cn.chen.proxy.Moveable {
public $Proxy1(InvocationHander h) {
this.h = h;
}
cn.chen.proxy.compiler.InvocationHander h;
@Override
public void move(){
try{
Method method = cn.chen.proxy.Moveable.class.getMethod("move");
h.invoke(this,method);
}catch(Exception e){e.printStackTrace();}}
}
测试
package cn.chen.proxy.compiler.test;
public interface UserMgr {
void addUser();
}
package cn.chen.proxy.compiler.test;
public class UserMgrImpl implements UserMgr{
@Override
public void addUser() {
System.out.println("1.插入记录到User表");
System.out.println("2.做日志在另外一张表");
}
}
package cn.chen.proxy.compiler.test;
import cn.chen.proxy.Proxy;
import cn.chen.proxy.compiler.InvocationHander;
public class Client {
public static void main(String[] args) throws Exception {
UserMgr userMgr = new UserMgrImpl();
InvocationHander h = new TransacationHandler(userMgr);
UserMgr u = (UserMgr) Proxy.newProxyInstance(UserMgr.class, h);
u.addUser();
}
}
package cn.chen.proxy.compiler;
import java.lang.reflect.Method;
public class $Proxy1 implements cn.chen.proxy.compiler.test.UserMgr {
public $Proxy1(InvocationHander h) {
this.h = h;
}
cn.chen.proxy.compiler.InvocationHander h;
@Override
public void addUser(){
try{
Method method = cn.chen.proxy.compiler.test.UserMgr.class.getMethod("addUser");
h.invoke(this,method);
}catch(Exception e){e.printStackTrace();}}
}
class cn.chen.proxy.compiler.$Proxy1
Transaction start
1.插入记录到User表
2.做日志在另外一张表
Transaction commit
Process finished with exit code 0
我们模拟了JDK动态代理的内部实现,接下来我们使用JDK提供的Proxy来实现动态代理:JDK提供的动态代理