/* * 接口中有几个方法,那么使用反射的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 */ } }