今天我们让它能代理所有接口
(在看这篇文章之前 请一定先看看上一篇)
先看看项目目录
为了做出在被代理对象前后做操作的逻辑 我们写出下面这个类
package proxy; import java.lang.reflect.Method; public class TimeInvHan implements InvocationHandler { public TimeInvHan(Object object) { super(); this.obj = object; } Object obj; @Override public void invoke(Method m, Object o) { long start = System.currentTimeMillis(); System.out.println("starttime:" + start); try { m.invoke(obj, new Object[]{}); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } long end = System.currentTimeMillis(); System.out.println("end time:" + end); System.out.println("expend time:" + (end - start)); } }
TimeInvHan 里面有个Object类型的属性obj 它所代表的就是被代理的对象 (就是最原始的那个坦克)
再看invoke 这个方法
Method m 这是我们被代理对象的方法 (在说简单点就是 move方法)
Object o 这个参数我们类里没有用到 (我们所讨论的情况 比较简单 但是在复杂的情况下这个o就会用到了)
m.invoke(obj, new Object[]{});
这行代码就更简单了 就是调用obj的m方法 其参数为new Object[]{} ----(就是为空)
然后我们在这个核心代码前后加上 我们要的逻辑 --记录时间
InvocationHandler 这个接口也很简单 如下
package proxy; import java.lang.reflect.Method; public interface InvocationHandler { void invoke(Method m,Object o); }
public static Object newInstance(Class h,InvocationHandler in) throws Exception{ String rt = "\r\n"; String methodstr=""; Method[] methods=h.getMethods(); for(Method m:methods){ methodstr+="@Override"+rt; methodstr+="public "+m.getReturnType()+" "+m.getName()+"() { "+rt +" try{" + rt +" Method md = " + h.getName() + ".class.getMethod(\"" + m.getName() + "\");" + rt +" h.invoke(md,"+"this);" +rt +" }catch(NoSuchMethodException | SecurityException e){"+rt +" e.printStackTrace();" +rt +" }" + rt +" }"; } String src = "package proxy.compiler.test;" + rt + "import proxy.InvocationHandler;"+rt + " import java.lang.reflect.Method;"+rt + "public class Proxy1 implements "+ h.getName() + "{" + rt + " public Proxy1(InvocationHandler t) {" + rt + " super();" + rt +" this.h = t;" + rt + " }" + rt + " InvocationHandler h;" + rt + methodstr+rt+ "}"; } ........ }String methodstr="";
上面这部分就是将h这个接口里面的所有方法都放入字符串中
下面是proxy的全部代码
package 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 newInstance(Class h,InvocationHandler in) throws Exception{ String rt = "\r\n"; String methodstr=""; Method[] methods=h.getMethods(); for(Method m:methods){ methodstr+="@Override"+rt; methodstr+="public "+m.getReturnType()+" "+m.getName()+"() { "+rt +" try{" + rt +" Method md = " + h.getName() + ".class.getMethod(\"" + m.getName() + "\");" + rt +" h.invoke(md,"+"this);" +rt +" }catch(NoSuchMethodException | SecurityException e){"+rt +" e.printStackTrace();" +rt +" }" + rt +" }"; } String src = "package proxy.compiler.test;" + rt + "import proxy.InvocationHandler;"+rt + " import java.lang.reflect.Method;"+rt + "public class Proxy1 implements "+ h.getName() + "{" + rt + " public Proxy1(InvocationHandler t) {" + rt + " super();" + rt +" this.h = t;" + rt + " }" + rt + " InvocationHandler h;" + rt + methodstr+rt+ "}"; String fileName ="d:/src/proxy/compiler/test/Proxy1.java"; File f = new File(fileName); FileWriter fw = new FileWriter(f); fw.write(src); fw.flush(); fw.close(); //compoler JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileManager = javaCompiler .getStandardFileManager(null, null, null); Iterable units = fileManager.getJavaFileObjects(fileName); CompilationTask task = javaCompiler.getTask(null, fileManager, null, null, null, units); task.call(); fileManager.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("proxy.compiler.test.Proxy1"); Constructor cons= c.getConstructor(InvocationHandler.class); Object m=cons.newInstance(in); return m; } }
//这是测试代码 package proxy; public class Client { public static void main(String[] args) throws Exception { Say a=new SayHelloOrCurse(); InvocationHandler in= new HelloLogInvHan(a); Say s=(Say)Proxy.newInstance(Say.class, in); s.hello(); } } package proxy; public class SayHelloOrCurse implements Say { @Override public void hello() { // TODO Auto-generated method stub System.out.println("hello world"); } @Override public void curse() { // TODO Auto-generated method stub System.out.println("i curse you"); } } package proxy; public interface Say { void hello(); void curse(); } 测试结果如下 start log: hello world end log:
在Proxy.newInstance中
我们把类保存到了如下的位置
String fileName ="d:/src/proxy/compiler/test/Proxy1.java";
在相应位置可以找到Proxy1 如下
package proxy.compiler.test; import proxy.InvocationHandler; import java.lang.reflect.Method; public class Proxy1 implements proxy.Say{ public Proxy1(InvocationHandler t) { super(); this.h = t; } InvocationHandler h; @Override public void hello() { try{ Method md = proxy.Say.class.getMethod("hello"); h.invoke(md,this); }catch(NoSuchMethodException | SecurityException e){ e.printStackTrace(); } }@Override public void curse() { try{ Method md = proxy.Say.class.getMethod("curse"); h.invoke(md,this); }catch(NoSuchMethodException | SecurityException e){ e.printStackTrace(); } } }
package JDKProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class LogInvHan implements InvocationHandler { public LogInvHan(Object object) { super(); this.obj = object; } Object obj; @Override public Object invoke(Object proxy, Method method, Object[] args)throws Throwable { System.out.println("start log:" ); try { method.invoke(obj, new Object[]{}); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("end log:" ); return null; } }
package JDKProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class JdkProxyTest { public static void main(String[] args) { Imoveable t=new Tank(); InvocationHandler h=new LogInvHan(t); Imoveable m=(Imoveable)Proxy.newProxyInstance(t.getClass().getClassLoader(), t.getClass().getInterfaces(), h); InvocationHandler ha=new TimeInvHan(m); Imoveable m2=(Imoveable)Proxy.newProxyInstance(t.getClass().getClassLoader(), t.getClass().getInterfaces(), ha); m2.move(); } }
Imoveable t=new Tank(); InvocationHandler h=new LogInvHan(t); InvocationHandler ha=new TimeInvHan(h); Imoveable m=(Imoveable)Proxy.newProxyInstance(t.getClass().getClassLoader(), t.getClass().getInterfaces(), ha); m.move();