一分钟教你实现拦截器架构

软件老王

共 3261字,需浏览 7分钟

 ·

2020-10-27 15:40



拦截器主要用于拦截用户请求并作相应的处理.

例如, 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 List interceptors = 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 List getInterceptors() {    return Collections.unmodifiableList(interceptors);  }}

链节点:

public interface Interceptor {  Object intercept(Invocation invocation) throws Throwable;  Object plugin(Object target);}
public class LogInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { System.out.println(Thread.currentThread().getName()+ "\tlog intercept..."+ invocation.toString()); return invocation.proceed();    } @Override 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模块.



总结

万物之始, 大道至简, 衍化至繁.

通过代理和责任链两个非常简单的模式, 就可以设计出高扩展性, 低耦合的架构.

END/往期推荐:




1.微服务实战系列

2.springboot从入门到精通

3.java入门到精通

4.中间件等

5.程序人生

更多信息请关注公众号:「软件老王」,关注不迷路,软件老王和他的IT朋友们,分享一些他们的技术见解和生活故事。

浏览 19
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报