动态反射代理实现机制两例代码比较,最近研究设计模式,略作深入分析基于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
*/
第一种实现方式,接着请看第二篇文章.............^_^