您的位置:首页 > 编程语言 > Java开发

JDK动态代理说明

2011-06-23 21:22 295 查看
       如果我们想实现类似AOP的思想,自己写代码用代理或叫装饰模式也是可以实现的,但这样我们就面临必须给每个需要被装饰(我们暂时就叫它装饰吧)的接口写装饰子类,通过添加自己需要的特定功能并委托实体接口子类完成本体行为。这样我们需要写很多代码,而且很多时候都是重复代码,当然用种种模式可以把重复代码消减到最少,但看起来还是不怎么完美。

       这时候JDK的动态代理就其作用了,它帮我们减少了大量代码的编写工作,使我们可以将注意力放在我们需要添加的特定行为上。那JDK的动态代理又是如何完成的呢?它是通过动态继承基类Proxy并实现我们要代理的接口,将接口实现委托给InvocationHandler中的invoke, 将调用方法以参数形式传给invoke,同时InvocationHandler的子类持有真正的实体类对象以供方法调用。

JDK中动态代理就是代理模式的变体。如图

 


再看一例子:

public interface Hello {

public void say();
}

public class HelloImpl implements Hello {

public void say() {
System.out.println("hello world");
}
}

public class ConcreteInvocationHandler implements InvocationHandler {

private Object realObject;

public ConcreteInvocationHandler(Hello realObject) {
this.realObject = realObject;
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before method operation");
method.invoke(realObject, new Object[0]);
System.out.println("after method operation");
return null;
}
}

public static void main(String[] args) {
Hello hello = (Hello) Proxy.newProxyInstance(Hello.class.getClassLoader(), new Class[] { Hello.class },
new ConcreteInvocationHandler(new HelloImpl()));
hello.say();
}


 

上面的实现已经可以实现我们动态给某个方法添加其他功能了,但是它只能加一次,如果我们能以一种链化的动态代理,可以添加多层拦截那对实际应用可能更有效果,由此我们可以改变一下我们的设计,如图:


 

 

为了更好理解,看下例子。

public interface CustomInvocationHandler extends InvocationHandler {

public void doBefore();

public void doAfter();
}

public abstract class AbstractInvocationHandler implements CustomInvocationHandler {

protected Object realObject;

protected AbstractInvocationHandler successor;

protected AbstractInvocationHandler(Object realObject) {
this.realObject = realObject;
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
doBefore();
if (this.successor == null) {
result = method.invoke(this.realObject, args);
} else {
result = successor.invoke(proxy, method, args);
}
doAfter();
return result;
}

public void setSuccessor(AbstractInvocationHandler successor) {
this.successor = successor;
}
}

public class ConcreteInvocationHandler1 extends AbstractInvocationHandler {

protected ConcreteInvocationHandler1(Object realObject) {
super(realObject);
}

public void doAfter() {
System.out.println("doAfter1");
}

public void doBefore() {
System.out.println("doBefore1");
}
}

public class ConcreteInvocationHandler2 extends AbstractInvocationHandler {

protected ConcreteInvocationHandler2(Object realObject) {
super(realObject);
}

public void doAfter() {
System.out.println("doAfter2");
}

public void doBefore() {
System.out.println("doBefore2");
}
}

public class ConcreteInvocationHandler3 extends AbstractInvocationHandler {

protected ConcreteInvocationHandler3(Object realObject) {
super(realObject);
}

public void doAfter() {
System.out.println("doAfter3");
}

public void doBefore() {
System.out.println("doBefore3");
}
}

public class TestLinkedProxy {

public static void main(String[] args) {
Hello hello = new HelloImpl();
ConcreteInvocationHandler1 h1 = new ConcreteInvocationHandler1(hello);
ConcreteInvocationHandler2 h2 = new ConcreteInvocationHandler2(hello);
ConcreteInvocationHandler3 h3 = new ConcreteInvocationHandler3(hello);
h1.setSuccessor(h2);
h2.setSuccessor(h3);
Hello h = (Hello) Proxy.newProxyInstance(Hello.class.getClassLoader(), new Class[] { Hello.class }, h1);
h.say();
}
}


 

再看下运行结果:

doBefore1
doBefore2
doBefore3
hello world
doAfter3
doAfter2
doAfter1

 

OK了,经过改造我们可以实现链化动态代理了,对于实际应用更能体现我们对各个层面上的切入
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息