读书人

模拟JDK动态署理

发布时间: 2012-08-30 09:55:54 作者: rapoo

模拟JDK动态代理

接口Moveable:public interface Moveable { public void move(); public void stop();}接口的实现类Tank:public class Tank implements Moveable{        public void move() {       System.out.println("tank is moving...");       try {           Thread.sleep(new Random().nextInt(10000));       } catch (InterruptedException e) {           e.printStackTrace();       }    }    @Override    public void stop() {       System.out.println("tank stoped...");    }}模拟的InvocationHandler:public interface InvocationHandler {    public void invoke(Object object,Method method);}InvocationHandler的实现,也即应用类LogHandler:public class LogHandler implements InvocationHandler{    private Object target;//被代理对象    public LogHandler(Object object) {       super();       this.target = object;    }    @Override    public void invoke(Object object,Method method) {       //先调用自己的逻辑,然后调用被代理对象的方法,最后再调用自己的逻辑       System.out.println("log begin...");       try {           method.invoke(target);       } catch (Exception e) {           e.printStackTrace();       }       System.out.println("log end...");    }}本文中最重要的代理类Proxy:public class Proxy {    public static Object newProxyInstance(Class interClass,InvocationHandler handler) throws Exception{       String srcString="";//源代码字符串       String rt = "\r\n";//回车换行符       String methodString = "";//方法字符串       Method[] methods = interClass.getMethods();//找出接口interClass中的所有方法       for(Method method:methods){           //将接口中的所有方法拼接为方法字符串           methodString +=                      "   public void " + method.getName() +"(){" + rt +//方法头部                     "   try{" + rt +                     "      Method md = " +interClass.getName() +".class.getMethod(\"" + method.getName() +"\");" + rt +//获得接口中的一个方法                     "      handler.invoke(this,md);" + rt +//用处理器handler进行处理                     "   }catch(Exception e){" + rt +                     "      e.printStackTrace();" + rt +                     "   }" + rt +                     "   }" + rt ;       }       srcString = "package com.hibernate.proxy;" + rt +                  "import java.lang.reflect.Method;" + rt +                  "public class $Proxy1 implements "+ interClass.getName() + "{" + rt +//此处应注意:@Proxy1一定要记得实现传过来的接口                  "   private InvocationHandler handler;" + rt +//代理中应该保存一个处理器handler,并在构造函数中进行传递                  "   public $Proxy1(InvocationHandler handler){" +rt +                  "      this.handler = handler;" + rt +                  "   }" + rt +                  methodString + rt +                  "}";       String fileName = System.getProperty("user.dir")+"/src/com/hibernate/proxy/$Proxy1.java";//这个是文件的名称       File file = new File(fileName);//新建文件       if(!file.exists()){           file.createNewFile();       }       FileWriter writer = new FileWriter(file);       writer.write(srcString);//将源代码写到文件中       writer.flush();       writer.close();       //以下的部分是对刚才新建的源代码文件尽心编译       JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();       StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);       Iterable units = manager.getJavaFileObjects(fileName);       CompilationTask task = compiler.getTask(null, manager, null, null, null, units);       task.call();       manager.close();       //将编译后的文件加载到内存       URL[] urls = new URL[]{new URL("file:/" + System.getProperty("user.dir"+"/src"))};       URLClassLoader classLoader = new URLClassLoader(urls);       Class class1 = classLoader.loadClass("com.hibernate.proxy.$Proxy1");       //生成新的对象       //获得代理对象$proxy1的构造方法,并将参数的类型传给它       Constructor constructor = class1.getConstructor(InvocationHandler.class);       //构造一个新的代理对象,参数为传进来的handler       Object object = (Object)constructor.newInstance(handler);       //返回新生成的代理对象       return object;    }}测试类:public class ProxyTest {    public static void main(String[] args) {       Tank tank = new Tank();       InvocationHandler handler = new LogHandler(tank);       try {           Moveable moveable = (Moveable)Proxy.newProxyInstance(Moveable.class, handler);//生成一个和被代理对象具有相同接口的代理对象           moveable.move();           moveable.stop();       } catch (Exception e) {           e.printStackTrace();       }    }}编译生成的$Proxy1类:package com.hibernate.proxy;import java.lang.reflect.Method;public class $Proxy1 implements com.hibernate.proxy.Moveable{    private InvocationHandler handler;    public $Proxy1(InvocationHandler handler){       this.handler = handler;    }    public void stop(){    try{       Method md = com.hibernate.proxy.Moveable.class.getMethod("stop");       handler.invoke(this,md);    }catch(Exception e){       e.printStackTrace();    }    }    public void move(){    try{       Method md = com.hibernate.proxy.Moveable.class.getMethod("move");       handler.invoke(this,md);    }catch(Exception e){       e.printStackTrace();    }    } }

?

读书人网 >编程

热点推荐