动态反射代理实现机制两例代码比较,最近研究设计模式,略作深入分析基于JDK1.3以来的Java动态反射代理,也结合最新的JDK1.6版本以上的新特性进行比较,业界主要有CGLIB、ASM等技术实现生成字节码。
通常我们使用反射代理这种统一处理方式针对一致日志、事务、权限、监控、拦截等这种具有切面点的场景进行一系列的自动处理,减轻程序员的代码编写量,提升代码的耦合度,适当提升代码编写质量,对系统架构的扩展性进一步加强。此处放在这里做一个参考比较,学习使用,抛砖引玉,以资共享......
由于时间紧迫,先写一个简单日后再完善......
第二种实现代码如下(基于JDK1.6以上的自带新特性):
被代理方法的接口类 Vehicleable.java:
/** * @author Dennis Zhao * @createdTime:Mar 29, 2013 */ public interface Vehicleable extends java.io.Serializable { void run(); void run(Car car); void run(Car car, MotoCar c); }
被代理方法的接口实现类 Vehicle.java:
import java.util.Random; /** * @author Dennis Zhao * @createdTime:Mar 29, 2013 */ public class Vehicle implements Vehicleable { private static final long serialVersionUID = 7633089691765059657L; @Override public void run() { System.out.println("Automatic Moving..."); try { Thread.sleep(new Random().nextInt(100)); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public void run(Car car) { String name = Car.class.getName(); System.out.println(name.substring(name.lastIndexOf(".") + 1) + " Moving..."); System.out.println("car name == " + car.getName() ); System.out.println("car color == " + car.getColor() ); System.out.println("car age == " + car.getAge() ); try { Thread.sleep(new Random().nextInt(100)); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public void run(Car car, MotoCar c) { String name = Car.class.getName(); String name1 = MotoCar.class.getName(); System.out.println(name.substring(name.lastIndexOf(".") + 1) + " and " + name1.substring(name1.lastIndexOf(".") + 1) + " Moving..."); System.out.println("car name == " + car.getName() ); System.out.println("car color == " + car.getColor() ); System.out.println("car age == " + car.getAge() ); System.out.println("motocar color == " + c.getColor() ); System.out.println("motocar name == " + c.getName() ); System.out.println("motocar age == " + c.getAge() ); try { Thread.sleep(new Random().nextInt(100)); } catch (InterruptedException e) { e.printStackTrace(); } } }
提供两个测试用的Javabea类Car.java, MotoCar.java
/** * @author Dennis Zhao * @createdTime:Mar 29, 2013 */ public class Car implements java.io.Serializable { private static final long serialVersionUID = 1L; private String name; private String color; private int age; public String getName() { return name; } public Car setName(String name) { this.name = name; return this; } public String getColor() { return color; } public Car setColor(String color) { this.color = color; return this; } public int getAge() { return age; } public Car setAge(int age) { this.age = age; return this; } }
MotoCar.java
/** * @author Dennis Zhao * @createdTime:Mar 29, 2013 */ public class MotoCar implements java.io.Serializable { private static final long serialVersionUID = 11L; private String name; private String color; private int age; public String getName() { return name; } public MotoCar setName(String name) { this.name = name; return this; } public String getColor() { return color; } public MotoCar setColor(String color) { this.color = color; return this; } public int getAge() { return age; } public MotoCar setAge(int age) { this.age = age; return this; } }
自定义一个模拟JDK接口类InvocationHandler.java
/** * 模拟 JDK InvocationHandler处理类 * @author Dennis Zhao * @createdTime:Mar 29, 2013 */ public interface InvocationHandler extends java.io.Serializable { public void invoke(Object o, Method m, Object... obj); }
接口类InvocationHandler的实现类LogHandler.java
import java.lang.reflect.Method; /** * 模拟日志包装处理类 * @author Dennis Zhao * @createdTime:Mar 29, 2013 */ public class LogHandler implements InvocationHandler{ private static final long serialVersionUID = -9124608101609510202L; private Object target; public LogHandler(Object target) { super(); this.target = target; } @Override public void invoke(Object o, Method m, Object... obj) { long start = System.currentTimeMillis(); System.out.println("正式的方法 log :" + start); //System.out.println(o.getClass().getName()); try { m.invoke(target, obj); } catch (Exception e) { e.printStackTrace(); } long end = System.currentTimeMillis(); System.out.println("运行 时间 log :" + (end-start)); } }
生成隐藏动态代理类HiddenProxy.java
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; /** * 隐藏代理类,完全动态生成执行,自定义代码 * @author Dennis Zhao * @createdTime:Mar 29, 2013 */ public class HiddenProxy { @SuppressWarnings("unchecked") public static Object newProxyInstance(Class> interfaces, InvocationHandler h) throws Exception { StringBuffer methodStr = new StringBuffer(""); String newLine = "\r\n"; String curPath = System.getProperty("user.dir"); String filePath = curPath + File.separator + "tmp" + File.separator; Method[] methods = interfaces.getMethods(); for(Method m : methods) { StringBuffer sb = new StringBuffer("");m.getParameterTypes(); StringBuffer sbp = new StringBuffer(""); Class[] cs = m.getParameterTypes(); for (Class c : cs) { String objName = c.getName(); sb.append(objName).append(" ") .append(objName.substring(objName.lastIndexOf(".") + 1).toLowerCase()) .append(","); sbp.append(sb.substring(sb.lastIndexOf(" ")+1)); } String strParam = ""; String param = ""; if(sb.length() > 0) { strParam = sb.substring(0, sb.length() - 1); param = "new Object[]{"+ sbp.substring(0, sbp.length() - 1) + "}"; } else { param = "new Object[]{}"; } int len = m.getParameterTypes().length; methodStr.append(newLine).append(" @Override").append(newLine) .append(" public void " + m.getName() + "(" + strParam + ") {" + newLine) .append(" try {" + newLine ) .append(" System.out.println(\"自定义事务开始...\");" + newLine) .append(" Method[] mds = " + interfaces.getName() + ".class.getMethods();").append(newLine) .append(" for(Method m : mds) {").append(newLine) .append(" if (m.getName().startsWith(\"" + m.getName() + "\") && ") .append( len+"==m.getParameterTypes().length) {").append(newLine) .append(" h.invoke(this, m, " + param + ");").append(newLine) .append(" break;").append(newLine) .append(" }").append(newLine) .append(" }").append(newLine) .append( newLine ) .append(" System.out.println(\"自定义事务完毕。 \" );" + newLine ) .append(" } catch(Exception e) {").append(newLine) .append(" e.printStackTrace();" + newLine ) .append(" }" + newLine ) .append(" }" + newLine) ; } StringBuffer src = new StringBuffer().append( "package com.pattern.proxy.aop.proxy;" + newLine) .append("import java.lang.reflect.Method;" + newLine) .append("import com.pattern.proxy.aop.proxy.InvocationHandler;" + newLine) .append("public class MyProxy implements " + interfaces.getName() + "{" + newLine) .append(" InvocationHandler h;" + newLine) .append(" public MyProxy(InvocationHandler h) {" + newLine ) .append(" this.h = h;" + newLine ) .append(" }" + newLine ) .append(methodStr + newLine ) .append("}"); String fileName = filePath + "com" + File.separator +"pattern" + File.separator + "proxy" + File.separator +"aop" + File.separator +"proxy" + File.separator; File f = new File(fileName); f.mkdirs(); fileName = fileName + "MyProxy.java"; File f1 = new File(fileName); FileWriter fw = new FileWriter(f1); fw.write(src.toString()); fw.flush(); fw.close(); //compile JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null); Iterable units = fileMgr.getJavaFileObjects(fileName); CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units); t.call(); fileMgr.close(); //load into memory and create an instance URL[] urls = new URL[] {new URL("file://" + filePath)}; URLClassLoader ul = new URLClassLoader(urls); Class> c = ul.loadClass("com.pattern.proxy.aop.proxy.MyProxy"); Constructor> ctr = c.getConstructor(InvocationHandler.class); Object m = ctr.newInstance(h); //System.out.println(m.getClass().getName()); return m; } }
最后测试类以及测试结果Test.java
/** * AOP模拟实现动态反射代理机制,基于 JDK1.6以上 * @author Dennis zhaoxiaobo * @createdTime:Mar 29, 2013 */ public class Test { public static void main(String[] args) throws Exception { Vehicle t = new Vehicle(); InvocationHandler h = new LogHandler(t); Vehicleable m = (Vehicleable)HiddenProxy.newProxyInstance(Vehicleable.class, h); m.run(); m.run(new Car().setName("abo car").setAge(12).setColor("black")); m.run(new Car().setName("my car").setAge(11).setColor("red"), new MotoCar().setColor("green").setName("Abo's motocar").setAge(100)); } } ////可以对任意的对象、任意的接口方法,实现任意的代理, 针对对象,注意(不支持基本数据类型) /* ------------ 打印测试结果-------------- 自定义事务开始... 正式的方法 log :1364539212298 Automatic Moving... 运行 时间 log :62 自定义事务完毕。 自定义事务开始... 正式的方法 log :1364539212360 Car Moving... car name == abo car car color == black car age == 12 运行 时间 log :78 自定义事务完毕。 自定义事务开始... 正式的方法 log :1364539212438 Car and MotoCar Moving... car name == my car car color == red car age == 11 motocar color == green motocar name == Abo's motocar motocar age == 100 运行 时间 log :110 自定义事务完毕。 */
指定生成了虚拟的Java类,帮我们做一些本应该由代理类来完成的工作。
由于工作事情多,有时间再整理做一些文字性补充说明.....^_^