前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一分钟教你实现拦截器架构

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

作者头像
一个架构师
发布2022-06-20 20:13:08
2590
发布2022-06-20 20:13:08
举报

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

例如, Spring MVC通过拦截器可以进行权限验证、记录日志等; Mybatis通过插件实现分页功能, 而这个插件就是拦截器.

架构图如下:

拦截器一般都是使用代理模式+责任链一起实现的, 下面一起看下这两种设计模式.

一. 代理模式

代理模式给某一个对象提供一个代理对象, 并由代理对象控制对原对象的引用.

代理模式是非常常见一个设计模式, 一般分为动态代理和静态代理, 我们以动态代理为例看下, 如何实现一套代理模式.

代理模式主要分为三部分: 接口, 实现类, 代理类.

接口:

代码语言:javascript
复制
public interface UserService {
 void addUser();
}

实现类:

代码语言:javascript
复制
public class UserServiceImpl implements UserService {
    public UserServiceImpl() {
    }
    public void addUser() {
        System.out.println("this is addUser() method!");
    }
}

代理类:

代码语言:javascript
复制
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;
    }
}

测试类:

代码语言:javascript
复制
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();
}

二. 责任链模式

为方便多个代理的扩展, 还需要引入过责任链模式. 责任链模式是一种对象的行为模式. 在责任链模式里, 很多对象由包含下一个对象引用的对象而连接起来形成一条链. 请求在这个链上传递, 直到链上的某一个对象决定处理此请求. 责任链设计模式能够根据配置, 自由组合, 动态调用.

责任链模式实现代码主要分为三部分: 责任链, 链节点, 处理实体.

结合上面的代理模式, 实现代码如下:

责任链:

代码语言:javascript
复制
public class InterceptorChain {
  private final List<Interceptor> interceptors = new ArrayList<Interceptor>();
  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<Interceptor> getInterceptors() {
    return Collections.unmodifiableList(interceptors);
  }
}

链节点:

代码语言:javascript
复制
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);
    }
}

处理实体:

代码语言:javascript
复制
public interface UserService {
 void addUser();
}

public class UserServiceImpl implements UserService {
    public UserServiceImpl() {}
    public void addUser() {
        System.out.println("this is addUser() method!");
    }
}

测试类

代码语言:javascript
复制
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模块.

总结

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

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 从码农的全世界路过 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档