首页 > 代码库 > Java代理小结
Java代理小结
在网上自学了下Java的代理,把贴出来代码做个笔记和总结
一、使用代理的目的
1、路由对远程服务器的方法调用
2、在程序运行期间,将用户接口事件和动作关联起来
3、为调试、跟踪方法调用等等
二、实现代理需要的类和接口包括:
1、用来生成代理类的Proxy类
2、被代理的类需要实现的接口,这里用的Moveable
3、调用处理器接口InvocationHandler
4、具体的被代理的类,这里是Tank,它实现Mobeable接口
5、实现调用处理器接口的包装器类,这里是TimeHandler
三、代理类是在Proxy类中动态生成,且必须要实现被代理类所实现的接口,代理类具有的方法有:
1、指定接口所需要的全部方法,这里是Moveable
2、Object类中的全部方法,例如:toString(),equals()等,因为Object是所有类的超类
下面的例子这里要实现的代理逻辑是,Tank类在每次调用move()方法之前和之后都记录一下当前的时间
首先是测试类
package proxy; import java.io.IOException; import java.lang.reflect.InvocationTargetException; public class ProxyTest { public static void main(String[] args) throws SecurityException, IllegalArgumentException, IOException, ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Tank t=new Tank(); InvocationHandler h=new TimeHandler(t); Moveable m=(Moveable) Proxy.newProxyInstance(Moveable.class,h); m.move(); } }
被代理类的接口
package proxy; public interface Moveable { public void move(); }
被代理的类
package proxy; public class Tank implements Moveable{ @Override public void move() { Thread t=new Thread(); t.start(); try { t.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("moving..."); }
时间处理的包装器,构造函数需要传递被代理的对象
package proxy; import java.lang.reflect.Method; import java.util.Date; public class TimeHandler implements InvocationHandler { Object target; public TimeHandler(Object target){ super(); this.target=target; } @Override public void invoke(Object o,Method m) { System.out.println("start time:"+new Date().toLocaleString()); try{ m.invoke(target); }catch(Exception e){ e.printStackTrace(); } System.out.println("end time:"+new Date().toLocaleString()); } }
最重要的Proxy
package proxy; import java.io.*; import java.lang.reflect.*; import java.net.*; import javax.tools.JavaCompiler; import javax.tools.JavaCompiler.CompilationTask; import javax.tools.; public class Proxy { public static Object newProxyInstance(Class intrfc,InvocationHandler h) throws IOException, ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { String mthStr="";//用来保存从intrfc中继承而来的所有方法的详细实现 Method[] methods=intrfc.getMethods();//用来保存intrfc的所有方法名 for(Method m:methods){ mthStr+="@Override" +" " + "public void "+m.getName()+"(){"+ "try{"+ "Method md="+intrfc.getName()+".class.getMethod(\""+m.getName()+"\");"+ "h.invoke(this,md);"+ "}catch(Exception e){"+ "}"+ "}"; } String str ="import java.lang.reflect.Method;" + "public class MyProxy implements "+ intrfc.getName()+"{" + "proxy.InvocationHandler h;" +"public MyProxy(proxy.InvocationHandler h ){" + "this.h=h;" + "}" +mthStr +"}"; String fileName ="D:/Workspaces/Eclipse/DesignPattern/src//MyProxy.java"; File f = new File(fileName); FileWriter fw = new FileWriter(f); fw.write(str); fw.flush(); fw.close(); //compile JavaCompiler compiler=ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileMgr=compiler.getStandardFileManager(null, null, null); Iterable units=fileMgr.getJavaFileObjects(fileName); CompilationTask task=compiler.getTask(null, fileMgr, null,null,null,units); task.call(); fileMgr.close(); //load进入内存 URL[] urls = new URL[] {new URL("file:/" + "D:/Workspaces/Eclipse/DesignPattern/src/")}; URLClassLoader ul = new URLClassLoader(urls); Class c=ul.loadClass("MyProxy"); //通过Class实例创建的对象必须含有默认构造函数, //TimepProxy类当中不含有默认构造函数,所以只能通过 //Constructor的实例来创建对象 Constructor ctr=c.getConstructor(InvocationHandler.class); Object m=ctr.newInstance(h); return m; } }关于代理类实现的核心部分
1、代理类只包含一个调用处理器的实例InvocationHandler h;
2、代理类实现了被代理类所实现的接口当中的所有方法,并将实现的细节交给了调用处理器h.invoke(this,md);
3、通过编译、类加载器等技术得到代理类的Class对象
4、通过Proxy.newProxyInstance()传递进来的调用处理器对象赋值给代理类并构造代理对象
5、将创建的代理对象返回给客户
Java代理小结
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。