在 Spring 中有拦截链这一说法,如何通过 JDK 实现一个简易的拦截链呢。起初的想法是动态代理模式加上链表,但是发现存在一个问题,被拦截的方法会多次被调用,因此又想到一个办法:使用用动态代理机制和装饰器模式。
为什么采用装饰器模式。理由如下,装饰器本质上是一条调用链,由内而外调用,这恰好符合拦截链的形式。
具体应该怎么做?
仔细想想设计模式中的代理模式是如何实现的。如图所示
我所要所要做的就是解决代理类的生成问题。为此我把【装饰器模式】引入其中
修改后的类图如下所示
其中 左边的为代理模式,右边为装饰器模式。左边的代理类是由右边的抽象拦截器生成
抽象拦截器的作用是: 1 、封装 InvocationHandler 类。 2 、生成代理类。 3 、装饰模式的核心。
废话不多写,来个具体的例子
public interface Messagable { public void send(String message,String target); }
public class Telephone implements Messagable { public void send(String message, String target) { System.out.println("Telephone: " + target + " " + message); } }
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public abstract class AopChain implements InvocationHandler{ protected Object srcObject; public Object bind(Object obj){ srcObject = obj; return Proxy.newProxyInstance( obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this); } }
public class Dater extends AopChain { public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable { System.out.println("该函数发生于"+ new Date()); return arg1.invoke(srcObject, arg2); } }
import java.lang.reflect.Method; public class ShowMethodName extends AopChain { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("方法名为 "+method.getName()); return method.invoke(srcObject, args); } }
public class TestAopChain { public static void main(String[] args){ Messagable telephone = new Telephone(); Messagable date = (Messagable)new Dater().bind(telephone); Messagable method = (Messagable)new ShowMethodName().bind(date); method.send("你在哪里?","小明"); } }
当然,这里还有很多不足,但是核心的一点,如何实现拦截这一问题已经做到。
如果还有问题,请大家多多指教。