Java 中责任链模式实现的三种方式

 更新时间:2017年09月11日 11:16:25   作者:atheva  
本文重点给大家介绍java中如何编写责任链模式。主要从下面3个框架中的代码中介绍。非常不错,需要的朋友参考下吧

责任链模式

责任链模式的定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系, 将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。这里就不再过多的介绍什么是责任链模式,主要来说说java中如何编写。主要从下面3个框架中的代码中介绍。

  • servlet中的filter
  • dubbo中的filter
  • mybatis中的plugin 这3个框架在实现责任链方式不尽相同。

servlet中的Filter

servlet中分别定义了一个 Filter和FilterChain的接口,核心代码如下:

public final class ApplicationFilterChain implements FilterChain {
  private int pos = 0; //当前执行filter的offset
  private int n; //当前filter的数量
  private ApplicationFilterConfig[] filters; //filter配置类,通过getFilter()方法获取Filter
  private Servlet servlet
  @Override
  public void doFilter(ServletRequest request, ServletResponse response) {
    if (pos < n) {
      ApplicationFilterConfig filterConfig = filters[pos++];
      Filter filter = filterConfig.getFilter();
      filter.doFilter(request, response, this);
    } else {
      // filter都处理完毕后,执行servlet
      servlet.service(request, response);
    }
  }
}

代码还算简单,结构也比较清晰,定义一个Chain,里面包含了Filter列表和servlet,达到在调用真正servlet之前进行各种filter逻辑。

Dubbo中的Filter

Dubbo在创建Filter的时候是另外一个方法,通过把Filter封装成 Invoker的匿名类,通过链表这样的数据结构来完成责任链,核心代码如下:

private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
  Invoker<T> last = invoker;
  //只获取满足条件的Filter
  List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
  if (filters.size() > 0) {
    for (int i = filters.size() - 1; i >= 0; i --) {
      final Filter filter = filters.get(i);
      final Invoker<T> next = last;
      last = new Invoker<T>() {
        ...
        public Result invoke(Invocation invocation) throws RpcException {
          return filter.invoke(next, invocation);
        }
        ...
      };
    }
  }
  return last;
}

Dubbo的责任链就没有类似FilterChain这样的类吧Filter和调用Invoker结合起来,而是通过创建一个链表,调用的时候我们只知道第一个节点,每个节点包含了下一个调用的节点信息。 这里的虽然Invoker封装Filter没有显示的指定next,但是通过java匿名类和final的机制达到同样的效果。

Mybatis中的Plugin

Mybatis可以配置各种Plugin,无论是官方提供的还是自己定义的,Plugin和Filter类似,就在执行Sql语句的时候做一些操作。Mybatis的责任链则是通过动态代理的方式,使用Plugin代理实际的Executor类。(这里实际还使用了组合模式,因为Plugin可以嵌套代理),核心代码如下:

public class Plugin implements InvocationHandler{
  private Object target;
  private Interceptor interceptor;
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {   
    if (满足代理条件) {
      return interceptor.intercept(new Invocation(target, method, args));
    }
    return method.invoke(target, args);   
  }
  //对传入的对象进行代理,可能是实际的Executor类,也可能是Plugin代理类
  public static Object wrap(Object target, Interceptor interceptor) {
    Class<?> type = target.getClass();
    Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
    if (interfaces.length > 0) {
      return Proxy.newProxyInstance(
          type.getClassLoader(),
          interfaces,
          new Plugin(target, interceptor, signatureMap));
    }
    return target;
  }
}

 简单的示意图如下:

总结

这里简单介绍了Servlet、Dubbo、Mybatis对责任链模式的不同实现手段,其中Servlet是相对比较清晰,又易于实现的方式,而Dubbo和Mybatis则适合在原有代码基础上,增加责任链模式代码改动量最小的。

以上所述是小编给大家介绍的Java 中责任链模式实现的三种方式,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章

  • 基于Java实现一个简单的单词本Android App的实践

    基于Java实现一个简单的单词本Android App的实践

    本文基于Java实现了一个简单的单词本安卓app,用的是SQLite数据库,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • Java中队列(Queue)和列表(List)的区别解析

    Java中队列(Queue)和列表(List)的区别解析

    Java中的列表(List)和队列(Queue)是两种常用的数据结构,它们分别用于不同的场景,列表是有序的,支持随机访问,允许重复元素,并且可以通过索引插入或删除元素,下面通过本文给大家介绍Java中队列(Queue)和列表(List)的区别,感兴趣的朋友一起看看吧
    2025-03-03
  • Java中Map循环遍历的五种方法实现

    Java中Map循环遍历的五种方法实现

    本文主要介绍了Java中Map循环遍历的五种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 深入理解Maven的坐标与依赖

    深入理解Maven的坐标与依赖

    这篇文章主要介绍了深入理解Maven的坐标与依赖,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • SpringBoot集成Redis使用Cache缓存的实现方法

    SpringBoot集成Redis使用Cache缓存的实现方法

    SpringBoot通过配置RedisConfig类和使用Cache注解可以轻松集成Redis实现缓存,主要包括@EnableCaching开启缓存,自定义key生成器,改变序列化规则,以及配置RedisCacheManager,本文为使用SpringBoot与Redis处理缓存提供了详实的指导和示例,感兴趣的朋友一起看看吧
    2024-10-10
  • Java利用PDFBox实现PDF文档基本操作

    Java利用PDFBox实现PDF文档基本操作

    这篇文章主要为大家详细介绍了java如何利用PDFBox实现PDF文档基本操作,例如创建PDF文档、加载PDF文档、获取总页数等,需要的小伙伴可以参考下
    2023-11-11
  • Springboot整合Dubbo教程之项目创建和环境搭建

    Springboot整合Dubbo教程之项目创建和环境搭建

    本篇文章主要介绍了Springboot整合Dubbo教程之项目创建和环境搭建,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • java中ArrayList 、LinkList的区别分析

    java中ArrayList 、LinkList的区别分析

    java中ArrayList 、LinkList的区别分析,需要的朋友可以参考一下
    2013-05-05
  • Java中LocalDateTime的具体用法

    Java中LocalDateTime的具体用法

    本文主要介绍了Java中LocalDateTime的具体用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • 详解Java中的checked异常和unchecked异常区别

    详解Java中的checked异常和unchecked异常区别

    这篇文章主要介绍了详解Java中的checked异常和unchecked异常区别,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-02-02

最新评论