/*
* 接口中有几个方法,那么使用反射的getMethods()就会有几个方法名
* 因为接口是不会继承Object的
*/
public interface Moveable {
void move();//
}
public class Car implements Moveable{
@Override
public void move() {
System.out.println("我是卡车,出发开往目的地...");
}
}
public interface UserMgr {
void addUser();
}
public class UserMgrImpl implements UserMgr {
@Override
public void addUser() {
System.out.println("1: 插入记录到user表");
System.out.println("2: 做日志在另外一张表");
}
}
//作为动态代理的预设框架,把需要增加的内容放入事先写好的功能中
public interface InvocationHandler {
/**
* @param obj 要代理类的对象car
* @param method 要代理类的对象car的代理方法
*/
void invoke(Object obj,Method method);
}
//对要代理类的对象的方法进行运行时间长短的测量
public class TimerInvocation implements InvocationHandler{
//target是要代理的对象,在客户端创建TimeInvocation时就进行传递
//为什么不在下面的invoke里直接传递obj为要代理的对象呢?
//那是因为在Proxy1类中要创建一个临时的代理对象$Proxy,然后这个$Proxy
//的对象会会调用这个TimerInvocation中的invoke方法,这个时候无法传递真
//正的要代理的对象,使用反射也不行,因为反射只会创建一个新的实例,而非一
//个拥有某种属性或功能的对象,故只能在客户端中进行传递
private Object target;
public TimerInvocation(Object target){
this.target=target;
}
//method是要代理的对象的方法
//这里的obj暂时没起到作用
@Override
public void invoke(Object obj, Method method) {
System.out.println("开始进行运行时间测量...");
long start=System.currentTimeMillis();
try {
method.invoke(target);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("共耗费时间:"+(System.currentTimeMillis()-start));
}
}
public class TransactionHandler implements InvocationHandler {
private Object target;
public TransactionHandler(Object target) {
super();
this.target = target;
}
@Override
public void invoke(Object o, Method m) {
System.out.println("Transaction Start");
try {
m.invoke(target);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Transaction Commit");
}
}
public class Proxy1 {
/**
*
* @param interfa 这个就是Moveable接口的class
* @param h 告诉Proxy类要产生的是什么类型的代理,可以是时间代理,日志代理
* 也就是要对interfa里的方法实现什么样的代理或功能
* @return
* 思路:
* 生成一个临时的代理类$Proxy,这个类继承于Moveable接口
* 这个类要去调用InvacationHandler的子类的invoke方法,实现切面的功能
* 然后返回这个临时代理类的对象,并让得到这个代理类的对象调用move()方法即可
*/
public static Object newProxyInstance(Class interfa,InvocationHandler h)throws Exception{
String rt="\r\n";
String java="package proxy1.dynamic;" + rt ;
java+="import java.lang.reflect.Method;" + rt ;
java+="public class $Proxy implements "+interfa.getName() +"{" + rt;
java+=" private InvocationHandler hand;" + rt;
java+=" public $Proxy(InvocationHandler hand){" + rt;
java+=" this.hand=hand;" + rt;
java+=" }" + rt;
Method[] methods=interfa.getMethods();
for(Method method : methods){//对接口interfa中的方法进行实现
java+=" @Override" + rt;
java+=" public void "+method.getName()+"(){" + rt;
java+=" try{" + rt;
java+=" Method m="+interfa.getName()+".class.getMethod(\""+method.getName()+"\");" + rt;
java+=" hand.invoke(this,m);" + rt;
java+=" }catch(Exception e){e.printStackTrace();}" + rt;
java+=" }" + rt;
}
java+="}" + rt;
System.out.println(java);
//创建java文件
String filepath=System.getProperty("user.dir")+"/src/proxy1/dynamic";
File file=new File(filepath+"/$Proxy.java");
try{
file.createNewFile();
FileWriter fw=new FileWriter(file);
fw.write(java);
fw.close();
}catch(Exception e){e.printStackTrace();}
//编译
JavaCompiler javac=ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager javafile=javac.getStandardFileManager(null, null, null);
String filename=filepath+"/$Proxy.java";
Iterable units=javafile.getJavaFileObjects(filename);
CompilationTask t=javac.getTask(null, javafile, null, null, null, units);
t.call();
try {javafile.close();
} catch (IOException e) {e.printStackTrace();}
//把刚才在D:/下生成的class文件CarTimeProxy.class加载进内存并生成实例对象
URL[] urls;
Object obj=null;
try {
urls = new URL[]{new URL("file:///D:/Workspaces/base/bin/")};
URLClassLoader classload=new URLClassLoader(urls);
Class clazz=classload.loadClass("proxy1.dynamic.$Proxy");
Constructor cons=clazz.getConstructor(InvocationHandler.class);
obj=cons.newInstance(h);
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
}
public class Client {
public static void main(String[] args) throws Exception {
/*Moveable move=new Car();
Moveable proxy=(Moveable) Proxy.newProxyInstance(move);
proxy.move();*/
/*Moveable move=new Car();
InvocationHandler hand=new TimerInvocation(move);
Moveable proxy=(Moveable)Proxy1.newProxyInstance(Moveable.class, hand);
proxy.move();*/
UserMgr mgr = new UserMgrImpl();
InvocationHandler h = new TransactionHandler(mgr);//先对日志进行捕获
UserMgr u = (UserMgr)Proxy1.newProxyInstance(UserMgr.class,h);
InvocationHandler h2 = new TimerInvocation(u);//再对时间进行测量
UserMgr u1 = (UserMgr)Proxy1.newProxyInstance(UserMgr.class,h2);
u1.addUser();
/**
* 运行结果:
* 开始进行运行时间测量...
* Transaction Start
* 1: 插入记录到user表
* 2: 做日志在另外一张表
* Transaction Commit
* 共耗费时间:0
*/
}
}
本文转自: http://blog.csdn.net/wxwzy738/article/details/7703990