动态反射代理实现机制两例代码比较,最近研究设计模式,略作深入分析基于JDK1.3以来的Java动态反射代理,也结合最新的JDK1.6版本以上的新特性进行比较。
通常我们使用反射代理这种统一处理方式针对一致日志、事务、权限、监控、拦截等这种具有切面点的场景进行一系列的自动处理,减轻程序员的代码编写量,提升代码的耦合度,适当提升代码编写质量,对系统架构的扩展性进一步加强。此处放在这里做一个参考比较,学习使用,抛砖引玉,以资共享......
由于时间紧迫,先写一个简单日后再完善......
第一种实现代码如下(基于JDK1.3以上的):
被代理方法的接口类 IVehicle.java:
/** * @author Dennis Zhao * @createdTime:Mar 22, 2013 */ public interface IVehicle extends java.io.Serializable { /** * 业务处理A方法 * @param name */ void doMethod1(String name); /** * 业务处理B方法 * @param name */ void doMethod2(String name); /** * * add * @param a * @param b * @return the int */ int add(int a, int b); /** * * getPerson * @param id * @return the Person */ Person getPerson(Long id); }
代理接口实现类Vehicle.java
/** * @author Dennis Zhao * @createdTime:Mar 22, 2013 */ public class Vehicle implements IVehicle { private static final long serialVersionUID = -4242273039478355706L; public void doMethod1(String name) { System.out.println("Hello, " + name); } public void doMethod2(String name) { System.out.println(name + ", GoodBye!"); } public int add(int a, int b) { return a + b; } @Override public Person getPerson(Long id) { final Person p = new Person("ABO", 33, 1l); p.setName("xiangzhouAPJ"); p.setId(id); return p; } }
使用到Javabean类Person.java
/** * @author Dennis Zhao * @createdTime:Mar 22, 2013 */ public class Person implements java.io.Serializable { private static final long serialVersionUID = 4341973142110996341L; private String name; private int age; private Long id; public Person(String name, int age, Long id) { this.name = name; this.age = age; this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String toString() { return "id = " + this.id + ", name = " + this.name; } }
日志等级枚举类Level.java
/** * @author Dennis Zhao * @createdTime:Mar 22, 2013 */ public enum Level { INFO,WARN,DEBUG; }
日志记录类Logger.java
import java.util.Date; /** * @author Dennis Zhao * @createdTime:Mar 22, 2013 */ public class Logger { /** */ /** * 根据等级记录日志 * @param level * @param contont */ @SuppressWarnings("deprecation") public static void logging(Level level, String contont) { if (level.equals(Level.INFO)) { System.out.println(String.format("%1$10s |%2$20s |%3$5s |%4$10s ", new Date().toLocaleString(), contont, "test", "日志记录开始....")); } if (level.equals(Level.DEBUG)) { System.out.println(String.format("%1$10s |%2$20s |%3$5s |%4$10s ", new Date().toLocaleString(), contont, "test", "日志记录结束。")); } } }
操作类接口类IOperation.java
/** * @author Dennis Zhao * @createdTime:Mar 22, 2013 */ public interface IOperation extends java.io.Serializable { /** * 方法执行之前的操作 * @param method */ void start(String name); /** * 方法执行之后的操作 * @param method */ void end(String name); }
操作类接口实现类LoggerOperation.java
/** * @author Dennis Zhao * @createdTime:Mar 22, 2013 */ public class LoggerOperation implements IOperation { private static final long serialVersionUID = -140781378476709074L; private String start; private String end; /** * @param start * @param end */ public LoggerOperation(String start, String end) { super(); this.start = start; this.end = end; } public void end(String name) { Logger.logging(Level.DEBUG, end + " Method end ."); } public void start(String name) { Logger.logging(Level.INFO, start + " Method Start!"); } public String getStart() { return start; } public void setStart(String start) { this.start = start; } public String getEnd() { return end; } public void setEnd(String end) { this.end = end; } }
关键的动态代理类DynamicProxy.java
/** * @author Dennis Zhao * @createdTime:Mar 22, 2013 */ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class DynamicProxy implements InvocationHandler { /** * 操作者,记录额外操作者 */ private Object proxy; /** * 被代理者 */ private Object delegate; /** * 动态生成方法被处理过后的对象 (写法固定) * @param delegate * @param proxy * @return Object */ public Object bind(Object delegate, Object proxy) { this.proxy = proxy; this.delegate = delegate; return Proxy.newProxyInstance( this.delegate.getClass().getClassLoader(), this.delegate .getClass().getInterfaces(), this); } /** * 自动动态处理调用对象的所有方法, 可以封装日志、事务、权限等 */ @SuppressWarnings("unchecked") public synchronized Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; try { //得到操作者的实例 Class clazz = this.proxy.getClass();; Method[] ms = clazz.getDeclaredMethods(); //前面对操作者追加内容的反射代理处理 for (Method m : ms) { if("start".equals(m.getName())) { Method start = clazz.getDeclaredMethod("start", m.getParameterTypes()); start.invoke(this.proxy, new Object[]{""}); break; } } //执行要处理对象的原本方法 真正执行的方法 result = method.invoke(this.delegate, args); //后面对操作者追加内容的反射代理处理 for (Method m : ms) { if("end".equals(m.getName())) { Method end = clazz.getDeclaredMethod("end", m.getParameterTypes()); end.invoke(this.proxy, new Object[]{""}); break; } } } catch (Exception e) { e.printStackTrace(); } return result; } }
测试类Test.java,以及测试结果
/** * @author Dennis Zhao * @createdTime:Mar 22, 2013 */ public class Test { public static void main(String[] args) { IVehicle v = (IVehicle) new DynamicProxy().bind(new Vehicle(), new LoggerOperation("first", "second")); v.doMethod1("Double fish"); v.doMethod2("Red king dragon"); System.out.println(v.add(1, 4)); System.out.println(v.getPerson(1L)); } } /* Mar 29, 2013 2:28:57 PM | first Method Start! | test |日志记录开始.... Hello, Double fish Mar 29, 2013 2:28:57 PM | second Method end . | test | 日志记录结束。 Mar 29, 2013 2:28:57 PM | first Method Start! | test |日志记录开始.... Red king dragon, GoodBye! Mar 29, 2013 2:28:57 PM | second Method end . | test | 日志记录结束。 Mar 29, 2013 2:28:57 PM | first Method Start! | test |日志记录开始.... Mar 29, 2013 2:28:57 PM | second Method end . | test | 日志记录结束。 5 Mar 29, 2013 2:28:57 PM | first Method Start! | test |日志记录开始.... Mar 29, 2013 2:28:57 PM | second Method end . | test | 日志记录结束。 id = 1, name = xiangzhouAPJ */
第一种实现方式,接着请看第二篇文章.............^_^