留言与评论(共有 0 条评论) |
发布时间:2020-04-12 08:45:06
关于责任链模式,其有两种形式,一种是通过外部调用的方式对链的各个节点调用进行控制,从而进行链的各个节点之间的切换;另一种是链的每个节点自由控制是否继续往下传递链的进度,这种比较典型的使用方式就是Netty中的责任链模式。本文主要讲解我们如何在Spring中使用这两种责任链模式。
1. 外部控制模式
对于外部控制的方式,这种方式比较简单,链的每个节点只需要专注于各自的逻辑即可,而当前节点调用完成之后是否继续调用下一个节点,这个则由外部控制逻辑进行。这里我们以一个过滤器的实现逻辑为例进行讲解,在平常工作中,我们经常需要根据一系列的条件对某个东西进行过滤,比如任务服务的设计,在执行某个任务时,其需要经过诸如时效性检验,风控拦截,任务完成次数等过滤条件的检验之后才能判断当前任务是否能够执行,只有在所有的过滤条件都完成之后,我们才能执行该任务。那么这里我们就可以抽象出一个接口,其设计如下:
这里的方法只有一个参数,主要就是控制当前task是否需要被过滤掉,其有一个boolean类型的返回值,通过该返回值以告知外部控制逻辑是否需要将该task过滤掉。对于该接口的子类,我们只需要将其声明为Spring所管理的一个bean即可:
上面我们模拟声明了三个的子类,用于设计一系列的控制当前task是否需要被过滤的逻辑,结构上的逻辑其实比较简单,主要就是需要将其声明为Spring所管理的一个bean。下面是我们的控制逻辑:
在上述的控制逻辑中,对于过滤器的获取,只需要通过Spring的自动注入即可,这里注入的是一个,也就是说,如果我们有新的实例需要参与责任链的过滤,只需要将其声明为一个Spring容器所管理的bean即可。
这种责任链设计方式的优点在于链的控制比较简单,只需要实现一个统一的接口即可,其基本上能够满足大部分的逻辑控制,但是对于某些需要动态调整链的需求其就无能为力了。比如在执行到某个节点之后需要动态的判断是否执行下一个节点,或者说要执行某些分叉的节点等等。这个时候我们就需要将链节点的传递工作交由各个节点进行。
2. 节点控制模式
对于节点控制调用的方式,其主要有三个控制点:Handler,HandlerContext和Pipeline。Handler中是用于编写具体的业务代码的;HandlerContext则主要是用于对Handler进行包裹,并且用于控制进行下一个节点的调用的;Pipeline则主要是用于控制整体的流程调用的,比如对于任务的执行,其有任务的查询,任务的过滤和执行任务等等流程,这些流程整体的逻辑控制就是由Pipeline来控制的,在每个流程中又包含了一系列的子流程,这些子流程则是由一个个的HandlerContext和Handler进行梳理的。这种责任链的控制方式整体逻辑如下图所示:
从图中可以看出,我们将整个流程通过对象进行了抽象,这里主要分为了三个步骤:查询task,过滤task和执行task。在每个步骤中,我们都使用了一系列的链式调用。图中需要注意的是,在每次调用链的下一个节点的时候,我们都是通过具体的Handler进行的,也就是说是否进行链的下一个节点的调用,我们是通过业务实现方来进行动态控制的。
关于该模式的设计,我们首先需要强调的就是接口的设计,其设计如下所示:
这里的接口主要是对具体的业务逻辑的一个抽象,对于该主要有如下几点需要说明:
上述流程代码中,我们注意到,每个层级的方法中都有一个用于传递链相关的控制信息,这里我们来看一下其源码:
在中,我们需要说明如下几点:
前面我们讲解了和的具体实现,以及实现的过程中需要注意的问题,下面我们就来看一下进行流程控制的是如何实现的,如下是接口的定义:
这里 主要是定义了一个接口,该接口定义了一系列的层级调用,是每个层级的入口方法。如下是该接口的一个实现类:
关于的实现,主要有如下几点需要说明:
这里我们已经实现了,和,知道这些bean都是被Spring所管理的bean,那么我们接下来的问题主要在于如何进行整个链的组装。这里的组装方式比较简单,其主要需要解决两个问题:
这里的第一个问题比较好处理,因为通过ApplicationContext就可以获取实现了某个接口的所有bean,而第二个问题我们可以通过声明一个实现了BeanPostProcessor接口的类来实现。如下是其实现代码:
这里我们整个链的维护工作就已经完成,可以看到,现在基本上已经实现了前面图中整个链式流程的控制。这里需要说明的一点是,上面的方法的执行是在方法之后执行的,也就是说这里在执行时,整个是已经初始化完成了的。下面我们来看一下外部客户端如何进行整个链是流程的控制:
这里我们模拟了一个客户端的调用,首先创建了一个对象,然后依次调用其各个层级的方法,并且这里我们使用try…finally结构来保证方法一定会执行。如此我们就完成了整个责任链模式的构造。这里我们使用前面用到的时效性过滤的filter来作为示例来实现一个:
关于这里的具体业务我们需要说明的有如下几点:
3. 小结
如此,我们就通过两种方式实现了责任链模式,而且我们实现的责任链模式都是符合"开-闭"原则的,也就是说后续我们要为链添加新的节点的时候,只需要根据规范实现相应的接口即可,而无需处理链的维护相关的工作。关于第二种实现方式,这里我们并没有实现链节点的顺序控制功能,以及如何动态的添加或删除链的节点,更有甚者,如果控制每个Handler是单例的还是多例的。当然,有了前面的框架,这些点实现起来也比较简单,这里权当起到一个抛砖引玉的作用,读者朋友可根据自己的需要进行实现。
留言与评论(共有 0 条评论) |
全站搜索