在上一篇博客中分析了一下JAVA设计模式中的代理模式,其中动态代理中,又有一个十分重要的JDK动态代理,这篇文章主要是分析JDK动态代理究竟是如何实现的。
动态代理实现思路
实现功能:通过Proxy的newProxyInstance返回代理对象。
- 声明一段源码(动态产生代理)。
- 编译源码(JDK Compiler API),产生新的类(代理类)。
- 将这个类load到内存中,产生一个新的对象(代理对象)。
- return代理对象。
准备工作:
- 引入一个jar包commons-io-2.2.jar。
- 将项目中Build Path下的JRE换成JDK,因为JRE不支持编译。
实例:
首先,自定义一个接口InvocationHandler
public interface InvocationHandler { public void invoke(Object o,Method m); }
接着定义接口的实现类
public class TimeHandler implements InvocationHandler { private Object target; public TimeHandler(Object target) { super(); this.target = target; } @Override public void invoke(Object o, Method m){ try { System.out.println("日志开始打印....."); m.invoke(target); System.out.println("日志结束打印......"); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }
编写模拟动态代理实现的类
public class Proxy { public static Object newProxyInstance(Class infce,InvocationHandler h) throws Exception{ //window下的换行符 String rt = " "; String methodStr = ""; for(Method m : infce.getMethods()){ methodStr += "@Override" + rt + "public void " + m.getName() + "() {" + rt + "try{" + rt + "Method md = " + infce.getName() + ".class.getMethod("" + m.getName() + "");" + rt + "h.invoke(this,md);" + rt + "}catch(Exception e){e.printStackTrace();}" + rt + "}"; } //声明一段源码 String str = "package model;" + rt + "import java.lang.reflect.Method;" + rt + "import model.InvocationHandler;" + rt + "public class $Proxy0 implements " + infce.getName() + "{" + rt + "private InvocationHandler h;" + rt + "public $Proxy0(InvocationHandler h) {" + rt + "super();" + rt + "this.h = h;" + rt + "}" + rt + methodStr + rt + "}"; //产生代理类的java文件 String filename = System.getProperty("user.dir")+"/src/model/$Proxy0.java"; File file = new File(filename); FileUtils.writeStringToFile(file, str); /** *编译 *获取编译器 */ JavaCompiler complier = ToolProvider.getSystemJavaCompiler(); //创建文件管理者 StandardJavaFileManager fileMgr = complier.getStandardFileManager(null, null, null); //获取文件 Iterable units = fileMgr.getJavaFileObjects(filename); //编译任务 CompilationTask t = complier.getTask(null, fileMgr, null, null, null, units); //进行编译 t.call(); fileMgr.close(); //load到内存中 ClassLoader cl = ClassLoader.getSystemClassLoader(); Class c = cl.loadClass("model.$Proxy0"); //根据构造器初始化,产生代理类 Constructor ctr = c.getConstructor(InvocationHandler.class); return ctr.newInstance(h); } }
最后编写测试类
public class Test { /** * 测试类 * */ public static void main(String[] args) throws Exception { Car car = new Car(); //事务处理 InvocationHandler h = new TimeHandler(car); Moveable m = (Moveable) Proxy.newProxyInstance(Moveable.class,h); m.move(); } }