一分钟教你实现拦截器架构
拦截器主要用于拦截用户请求并作相应的处理.
例如, Spring MVC通过拦截器可以进行权限验证、记录日志等;
Mybatis通过插件实现分页功能, 而这个插件就是拦截器.
架构图如下:

拦截器一般都是使用代理模式+责任链一起实现的, 下面一起看下这两种设计模式.
一. 代理模式
代理模式给某一个对象提供一个代理对象, 并由代理对象控制对原对象的引用.
代理模式是非常常见一个设计模式, 一般分为动态代理和静态代理, 我们以动态代理为例看下, 如何实现一套代理模式.
代理模式主要分为三部分: 接口, 实现类, 代理类.
接口:
public interface UserService {void addUser();}
实现类:
public class UserServiceImpl implements UserService {public UserServiceImpl() {}public void addUser() {System.out.println("this is addUser() method!");}}
代理类:
public class UserServiceInvocationHandler implements InvocationHandler {private Object targetObject;public UserServiceInvocationHandler(Object targetObject) {this.targetObject = targetObject;}public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {System.out.println("do something");Object result = method.invoke(targetObject, args);return result;}}
测试类:
private static void test1() {UserService targetObject = new UserServiceImpl();UserServiceInvocationHandler proxy = new UserServiceInvocationHandler(targetObject);UserService object = (UserService) Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), proxy);object.addUser();}
二. 责任链模式
为方便多个代理的扩展, 还需要引入过责任链模式.
责任链模式是一种对象的行为模式. 在责任链模式里, 很多对象由包含下一个对象引用的对象而连接起来形成一条链. 请求在这个链上传递, 直到链上的某一个对象决定处理此请求.
责任链设计模式能够根据配置, 自由组合, 动态调用.
责任链模式实现代码主要分为三部分: 责任链, 链节点, 处理实体.
结合上面的代理模式, 实现代码如下:
责任链:
public class InterceptorChain {private final Listinterceptors = new ArrayList (); public Object pluginAll(Object target) {for (Interceptor interceptor : interceptors) {target = interceptor.plugin(target);}return target;}public void addInterceptor(Interceptor interceptor) {interceptors.add(interceptor);}public ListgetInterceptors() {return Collections.unmodifiableList(interceptors);}}
链节点:
public interface Interceptor {Object intercept(Invocation invocation) throws Throwable;Object plugin(Object target);}public class LogInterceptor implements Interceptor {public Object intercept(Invocation invocation) throws Throwable {System.out.println(Thread.currentThread().getName()+ "\tlog intercept..."+ invocation.toString());return invocation.proceed();}public Object plugin(Object target) {return Plugin.wrap(target, this);}}
处理实体:
public interface UserService {void addUser();}public class UserServiceImpl implements UserService {public UserServiceImpl() {}public void addUser() {System.out.println("this is addUser() method!");}}
测试类
private static void test2() {InterceptorChain chain = new InterceptorChain();chain.addInterceptor(new LogInterceptor());UserService service = new UserServiceImpl();UserService object = (UserService) chain.pluginAll(service);object.addUser();}
为适应更多应用场景, 可以在invoke()方法前后分别抽象出perHandler()和postHandler()方法, 进行更多扩展.
注: 这里的类设计来源于mybatis的plugin模块.
总结
万物之始, 大道至简, 衍化至繁.
通过代理和责任链两个非常简单的模式, 就可以设计出高扩展性, 低耦合的架构.
1.微服务实战系列
4.中间件等
更多信息请关注公众号:「软件老王」,关注不迷路,软件老王和他的IT朋友们,分享一些他们的技术见解和生活故事。
评论
