java学习之路----静态代理---动态代理-----AOP的前奏(AOP也是动态代理)(四)

2014-11-24 08:09:46 · 作者: · 浏览: 2
c void "+m.getName()+"() {"+ " long start=System.currentTimeMillis();"+ " t."+m.getName()+"();"+ " long end=System.currentTimeMillis();"+ " System.out.println((end-start));"+ " }";*/ methodsString=methodsString+ "@Override"+ " public void "+m.getName()+"() {"+ "Method md="+infc.getName()+".class.getMethod(\""+m.getName()+ "\");"+ "h.invoke(this,md) ;"+ " }"; } /*把这个类当成一个string的字符串(源码) 现在我们假设,我们能把这字符串编译,生成类,放在内存,来产生对象 动态代理就是你看不到代理类,你只需要调用一个方法( Proxy的newProxyInstance()方法), 会自动给你返回一个代理类对象,这个对象的产生是由内部动态的生成一段代码,编译完成的*/ //现在我们就来动态的编译这段代码(JDK6,complier API,CGlib,ASM(直接生成二进制的class文件)) String src= "package com.text;"+
"public class TankTimeProxy implements "+infc.getName()+"{"+ "public TankTimeProxy(InvocationHandler h) {"+ " this.h = h;" + " }"+ //" Moveable t;"+ "com.text.InvocationHandler h ; " + methodsString + "}"; //获取当前系统目录(就是项目根目录) String fileName=System. getProperty("user.dir")+ "/src/com/text/TankTimeProxy.java" ; //System.out.println(fileName); File f= new File(fileName); FileWriter writer= new FileWriter(f); writer.write(src); writer.flush(); writer.close(); //看是否生成代码,右键项目,刷新就OK了 /*****************编译********************/ //这句话的作用就是获取系统当前默认的编译器(其实就 javac) JavaCompiler compiler=ToolProvider. getSystemJavaCompiler(); //拿到java的编译器 System. out.println(compiler.getClass().getName()); StandardJavaFileManager filemag=compiler.getStandardFileManager( null, null, null);//文件的管理器 Iterable untis= filemag.getJavaFileObjects(fileName);//找到文件,把文件放在 Iterable中 CompilationTask t=compiler.getTask( null, filemag, null, null , null, untis );//编译文件任务 t.call(); //编译文件 filemag.close(); //编译之后,我们打开window show View 选择Navigator(这个可以看到类详细的变化,就是看得到class文件的产生) /********************load 到内存,和创建对象*************************/ //如果要使用class.loader,就必须保证这个class在 classpath的路径下 //因此我们要用一个特殊的loader URL [] urls= new URL[]{ new URL("file:/"+System. getProperty( "user.dir")+"/src" )}; URLClassLoader ul= new URLClassLoader(urls);//这里需要一个数组地址 Class c=ul.loadClass("com.text.TankTimeProxy" );//把类加到内存 System. out.println(c); //反射来创建对象 Constructor ctr= c.getConstructor(InvocationHandler. class ) ;//获取构造方法 Object m=ctr.newInstance(h); return m; }
}
我在代码中增加一个叫InvocationHandler 的类,它的功能就是告诉我,什么对象要来实现什么功能

来理一下思路: 我要实现什么功能?(这里是我要?如果其他人喃?)
那就变成:什么人要实现什么功能?(object o ,Method m)
public interface InvocationHandler {//指定方法(你需要时间,日志,还是其他) public void invoke(Object o,Method m) throws Exception;//告诉那个对象去执行这个方法 }

比如说我要实现计时的功能 我传递的参数就是(I, time)
我们来写一下实现类
public class TimeHandler implements InvocationHandler{
@Override public void invoke(Object o,Method m) throws Exception{ long start=System. currentTimeMillis(); m.invoke(o, null ); long end=System. currentTimeMillis(); System. out.println((end-start)); }
}
我们运行下代码,发现出错了
这是因为我们不是代理 一个具体类来实现功能吗?但是现在却看到具体类的影子?
比如:我们要代理Tank 实现计时功能,就要传入Tank类
我们来修改一下代码:
public class TimeHandler implements InvocationHandler{ private Object t;
public TimeHandler(Object t) { super(); this.t = t; }

@Override public void invoke(Object o,Method m) throws Exception{ long start=System. currentTimeMillis(); m.invoke( t); long end=System. currentTimeMillis(); System. out.println((end-start)); }
}
测试类:
public class Client { public static void main(String[] ar