likes
comments
collection
share

设计模式:诠释抽象责任链模式的实际应用场景

作者站长头像
站长
· 阅读数 21

一、什么是责任链模式?

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许多个对象按照顺序处理请求,并且每个对象可以选择自己是否处理该请求或将其传递给下一个对象。这种模式将请求的发送者和接收者解耦,同时提供了更大的灵活性和可扩展性。

责任链模式通过将多个处理请求的对象组成一条链,使请求在链上传递,直到有一个对象处理它为止。每个处理对象都负责判断自己能否处理该请求,如果可以则进行处理,否则将请求传递给下一个处理对象。这样,请求发送者无需知道具体的处理对象,只需将请求发送到责任链上即可。

责任链模式包含以下角色:

  • 抽象处理者(Handler) :定义一个处理请求的接口,并持有下一个处理者的引用。
  • 具体处理者(Concrete Handler) :实现抽象处理者的接口,在处理请求前判断自己是否能够处理该请求,如果可以则进行处理,否则将请求传递给下一个处理者。

通过责任链模式,我们可以动态地组合处理对象,灵活地配置处理流程,这种解耦使得系统更加灵活和可扩展,一起看下责任链模式的执行流程。

设计模式:诠释抽象责任链模式的实际应用场景

设计模式只是帮助减少代码的复杂性,让其满足开闭原则,提高代码的扩展性。如果不使用同样可以完成需求。

责任链模式的应用场景

  1. 多个对象可以处理一个请求,但具体由哪个对象处理该请求在运行时自动确定。
  2. 可动态指定一组对象处理请求,或添加新的处理者。
  3. 需要在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。

假设业务场景是这样的,我们C端用户扫码进来选择套餐启动设备,系统会处于一个上游检测校验服务,判断是否满足相关复杂的套餐计算后才决定是否向用户推荐VIP活动套餐,因此会根据入参做一系列的check校验逻辑,从系统业务交谈规则上看,我简化了主要需要支持一下几种condition校验规则:

  1. 请求参数必填校验,如果数据无法满足业务所必须字段要求,数据一旦落入库中就会产生一系列问题。
  2. 当前活动信息校验,比如商家是否参与活动、活动配置信息是否正常、活动是否处于上架状态等。
  3. 时间校验,比如当前时间是否处于活动的开放时间范围内。
  4. 设备是否正常存在。
  5. 活动配置设备类型、场地类型限制校验。
  6. 次数校验,用户参与活动次数是否已经达到上限。

如果不使用责任链模式,上面说的真实同步场景面临两个问题:

  1. 如果把上述说的代码逻辑校验规则写到一起,毫无疑问这个类或者说这个方法函数奇大无比。减少代码复杂性一贯方法是:将大块代码逻辑拆分成函数,将大类拆分成小类,是应对代码复杂性的常用方法。如果此时说:可以把不同的校验规则拆分成不同的函数,不同的类,这样不也可以满足减少代码复杂性的要求么。这样拆分是能解决代码复杂性,但是这样就会面临第二个问题
  2. 开闭原则:添加一个新的功能应该是,在已有代码基础上扩展代码,而非修改已有代码。大家设想一下,假设你写了三套校验规则,运行过一段时间,这时候领导让加第四套,是不是要在原有代码上改动。

综上所述,在合适的场景运用适合的设计模式,能够让代码设计复杂性降低,变得更为健壮。朝更远的说也能让自己的编码设计能力有所提高。

使用责任链模式改造优点

  1. 将请求与处理解耦。
  2. 请求处理者(节点对象)只需要关注自己感兴趣的请求进行处理即可,对于不感兴趣的请求,转发给下一个节点。
  3. 具备链式传递处理请求功能,请求发送者无需知晓链路结构,只需等待请求处理结果。
  4. 链路结构灵活,可以通过改变链路的结构动态的新增或删减责任。
  5. 易于扩展新的请求处理类(节点),符合开闭原则

二、责任链模式模版

对于不同业务场景的责任链模式,我自定义了一套模版,适用于不同场景直接可以套用即可。

第一步:定义@Duty注解

一切从注解开始,需要自定义一个注解@Duty,这个注解由Spring@Component注解修饰,也就是标记了这个自定义注解的类,都是交给Springbean容器去管理 。

注解中,有两个属性:

  • mark:定义相同的mark标记类型的bean,会被放到一个责任链集合中。
  • order:同一个责任链集合中,bean的排序,数值越小,会放到链路最先的位置,优先处理。

设计模式:诠释抽象责任链模式的实际应用场景

第二步:定义一个顶层的抽象接口,入参为两个泛型参数,方便后续自定义扩展使用。

设计模式:诠释抽象责任链模式的实际应用场景

第三步:定义一个责任链处理器Bean的管理上下文AbstractChainContext,用来存放不同业务下的责任链路集合。在该类中,有一个Map和两个方法。

  • chainHandlerContainer:这个map会存放责任链路中,具体的执行类,key是注解@Duty中定义的mark值,value是标记了@Duty注解的bean集合,也就是具体的执行类集合。
  • applyHandleMap:传入具体执行bean的集合,存放在map中。
  • executeHandle:从chainHandlerContainer这个map中找到具体的执行bean集合,并依次执行。

设计模式:诠释抽象责任链模式的实际应用场景

第四步:定义一个配置类DutyDesignPatternConfiguration,用于装配上面的责任链管理器上下文AbstractChainContext

设计模式:诠释抽象责任链模式的实际应用场景

第五步:自定义不同责任链处理类

具体的处理类有:ActivityViewCheckParamAvailableChainHandlerActivityViewCheckActivityMerchantChainHandlerActivityViewCheckActivityGroupTypeChainHandlerActivityViewCheckActivityUpperLimitChainHandler,我这里以其中一个责任链的处理类为例,在具体处理类上标记自定义注解@Duty,该类会被注入到bean容器中,实现AbstractChainHandler接口,只需关心自己的handle方法,处理具体的业务逻辑。

设计模式:诠释抽象责任链模式的实际应用场景

第六步:具体调用

设计模式:诠释抽象责任链模式的实际应用场景

三、业务场景代码示例 - C端符合条件活动展示校验过滤器

ActivityViewCheckParamAvailableChainHandler参数校验处理类

设计模式:诠释抽象责任链模式的实际应用场景

ActivityViewCheckActivityMerchantChainHandler活动商家信息校验处理类

设计模式:诠释抽象责任链模式的实际应用场景

ActivityViewCheckActivityGroupTypeChainHandler场地和设备类型校验处理类

设计模式:诠释抽象责任链模式的实际应用场景

ActivityViewCheckActivityUpperLimitChainHandler商家参与活动次数校验处理类

设计模式:诠释抽象责任链模式的实际应用场景

实际调用

设计模式:诠释抽象责任链模式的实际应用场景

四、开源框架中责任链应用

责任链低耦合高扩展的特点让它在很多开源的框架中被采用,本文选取了开源框架中的 Spring InterceptorServlet FilterDubboSentinel 进行责任链的实现介绍,通过对常用框架中责任链应用的了解能够更好掌握责任链落地并在日常的开发中积极的使用。

4.1 Spring Interceptor

4.1.1 Interceptor介绍

设计模式:诠释抽象责任链模式的实际应用场景

  • Spring中的拦截器(Interceptor) 用于拦截控制器方法的执行,可以在方法执行前后添加自定义逻辑类似于AOP编程思想。
  • Inteceptor的作用时机是在请求(request)进入servlet后,在进入Controller之前进行预处理。
  • Inteceptor的实际应用包括:认证授权、日志记录、字符编码转换,敏感词过滤等等。
  • Inteceptor中责任链的实现会从处理器的介绍,责任链的构建以及责任链的执行三个角度进行阐述。

4.1.2 处理器介绍

public interface HandlerInterceptor {
 
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
    void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;
    void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;
}
 
@Component
public class TimeInterceptor extends HandlerInterceptorAdapter {
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 前置处理
        System.out.println("time interceptor preHandle");
 
        return true;
    }
 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 后置处理
        System.out.println("time interceptor postHandle");
    }
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("time interceptor afterCompletion");
    }
}

说明:

  • 处理器Interceptor的接口HandlerInterceptor定义了三个方法,可在控制器方法执行前后添加自定义逻辑。
  • 自定义处理器如上的TimeInterceptor需要自定义实现上述3个方法实现自我的逻辑。
  • 所有的自定义处理会串联在HandlerExecutionChain类实现的责任链上。

4.1.3 责任链构建

public class HandlerExecutionChain {
 
    private final Object handler;
    private HandlerInterceptor[] interceptors;
    private List<HandlerInterceptor> interceptorList;
    private int interceptorIndex = -1;
 
    public void addInterceptor(HandlerInterceptor interceptor) {
        // 添加拦截器
        initInterceptorList().add(interceptor);
    }
 
    public void addInterceptors(HandlerInterceptor... interceptors) {
        if (!ObjectUtils.isEmpty(interceptors)) {
            CollectionUtils.mergeArrayIntoCollection(interceptors, initInterceptorList());
        }
    }
 
    private List<HandlerInterceptor> initInterceptorList() {
        if (this.interceptorList == null) {
            this.interceptorList = new ArrayList<HandlerInterceptor>();
            if (this.interceptors != null) {
                // An interceptor array specified through the constructor
                CollectionUtils.mergeArrayIntoCollection(this.interceptors, this.interceptorList);
            }
        }
        this.interceptors = null;
        return this.interceptorList;
    }
}

说明:

  • HandlerExecutionChain类作为串联Interceptor处理器的责任链负责责任链的构建和执行。
  • HandlerExecutionChain类通过集合对象interceptorList保存所有相关的处理器对象。

4.1.4 责任链执行

public class DispatcherServlet extends FrameworkServlet {
 
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
 
        try {
            try {
                // mappedHandler代表的是HandlerExecutionChain责任链                 mappedHandler = getHandler(processedRequest);
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
 
                // 1、执行mappedHandler的applyPreHandle方法
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }
 
                // 2、执行controller的执行逻辑
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
 
                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }
                applyDefaultViewName(processedRequest, mv);
 
                // 执行mappedHandler的applyPostHandle方法
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            }
            catch (Exception ex) {
            }
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        catch (Exception ex) {
        }
        finally {
        }
    }
}
 
 
public class HandlerExecutionChain {
 
    private final Object handler;
    private HandlerInterceptor[] interceptors;
    private List<HandlerInterceptor> interceptorList;
    private int interceptorIndex = -1;
 
    boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HandlerInterceptor[] interceptors = getInterceptors();
        if (!ObjectUtils.isEmpty(interceptors)) {
            // 责任链从前往后的顺序执行
            for (int i = 0; i < interceptors.length; i++) {
                HandlerInterceptor interceptor = interceptors[i];
                if (!interceptor.preHandle(request, response, this.handler)) {
                    triggerAfterCompletion(request, response, null);
                    return false;
                }
                this.interceptorIndex = i;
            }
        }
        return true;
    }
 
    void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
        HandlerInterceptor[] interceptors = getInterceptors();
        if (!ObjectUtils.isEmpty(interceptors)) {
            // 责任链从后往前的顺序执行
            for (int i = interceptors.length - 1; i >= 0; i--) {
                HandlerInterceptor interceptor = interceptors[i];
                interceptor.postHandle(request, response, this.handler, mv);
            }
        }
    }
}

说明:

  • servletdoDispatch方法中依次触发责任链的applyPreHandle的前置处理方法、applyPostHandle的后置处理方法。
  • 前置处理方法applyPreHandle会遍历责任链上的处理器从前往后依次处理,后置处理方法applyPostHandle会遍历责任链上的处理器从后往前依次处理。
  • 处理器的驱动由责任链对象负责依次触发,非处理器对象自驱执行。

4.2 Servlet Filter

4.2.1 Filter介绍

设计模式:诠释抽象责任链模式的实际应用场景

  • Servlet过滤器是在Java Servlet规范2.3中定义的,它能够对Servlet容器的请求和响应对象进行检查和修改,是个典型的责任链。
  • Servlet被调用之前检查Request对象并支持修改Request HeaderRequest内容。
  • Servlet被调用之后检查Response对象并支修改Response HeaderResponse内容。

4.2.2 处理器介绍

public interface Filter {
    public void init(FilterConfig filterConfig) throws ServletException;
    public void doFilter ( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException;
    public void destroy();
}
 
public class TimeFilter implements Filter {
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("time filter init");
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 1、执行处理的逻辑
        System.out.println("time filter doFilter");
 
        // 2、执行责任链当中的下一个 Filter 对象,等价于执行 FilterChain 的internalDoFilter方法
        filterChain.doFilter(servletRequest, servletResponse);
    }
}

说明:

  • Servlet过滤器类要实现javax.servlet.Filter接口,该接口定义了通用的3个方法。
  • init方法:负责Servlet过滤器的初始化方法,Servlet容器创建Servlet过滤器实例过程中调用这个方法。
  • doFilter方法:当客户请求访问与过滤器关联的URL时,Servlet容器会调用该方法。
  • destroy方法:Servlet容器在销毁过滤器实例前调用该方法,可以释放过滤器占用的资源。

4.2.3 责任链构建

public final class ApplicationFilterChain implements FilterChain {
 
    // 责任链上 Filter 的维护对象
    private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
    //责任链上待执行的 Filter 对象
    private int pos = 0;
    // 责任链上拥有的 Filter 数量
    private int n = 0;
 
    void addFilter(ApplicationFilterConfig filterConfig) {
 
        // 避免重复添加Filter
        for(ApplicationFilterConfig filter:filters)
            if(filter==filterConfig)
                return;
        // 按需进行扩容
        if (n == filters.length) {
            ApplicationFilterConfig[] newFilters =
                new ApplicationFilterConfig[n + INCREMENT];
            System.arraycopy(filters, 0, newFilters, 0, n);
            filters = newFilters;
        }
        // 保存Filter 对象
        filters[n++] = filterConfig;
 
    }
}

说明:

  • ApplicationFilterChain作为Filter的责任链,负责责任链的构建和执行。
  • 责任链通过ApplicationFilterConfig类型的数组对象filters保存Filter处理器。
  • 责任链上处理器的添加通过保存到数组filters来实现。

4.2.4 责任链执行

public final class ApplicationFilterChain implements FilterChain {
 
    // 责任链上 Filter 的维护对象
    private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
    //责任链上待执行的 Filter 对象
    private int pos = 0;
    // 责任链上拥有的 Filter 数量
    private int n = 0;
 
    // 责任链的执行
    private void internalDoFilter(ServletRequest request,
                                  ServletResponse response)
        throws IOException, ServletException {
 
        // 在责任链未执行完的情况下执行责任链         if (pos < n) {
            // 获取当前待执行的 Filter,同时递增下一次待执行责任链的下标
            ApplicationFilterConfig filterConfig = filters[pos++];
            try {
                Filter filter = filterConfig.getFilter();
 
                if( Globals.IS_SECURITY_ENABLED ) {
                    // 省略相关代码
                } else {
                    filter.doFilter(request, response, this);
                }
            } catch (Throwable e) {
            }
            return;
        }
 
        try {
            if ((request instanceof HttpServletRequest) &&
                    (response instanceof HttpServletResponse) &&
                    Globals.IS_SECURITY_ENABLED ) {
                // 执行正常的业务逻辑
            } else {
                servlet.service(request, response);
            }
        } catch (Throwable e) {
            e = ExceptionUtils.unwrapInvocationTargetException(e);
            throw new ServletException(sm.getString("filterChain.servlet"), e);
        }
    }
}

说明:

  • 整个责任链上Filter处理器的执行通过处理器自驱进行实现,而非由责任链对象驱动。
  • Filter处理器的在处理过程中除了执行自我逻辑,会通过 filterChain.doFilter(servletRequest, servletResponse) h触发下一个处理器的执行。

4.3 Dubbo

4.3.1 Dubbo Filter介绍

设计模式:诠释抽象责任链模式的实际应用场景

  • DubboFilter作用时机如上图所示,Filter实现是专门为服务提供方和服务消费方调用过程进行拦截,Dubbo本身的大多功能均基于此扩展点实现,每次远程方法执行该拦截都会被执行。
  • Dubbo官方针对Filter做了很多的原生支持,目前大致有20来个吧,包括我们熟知的RpcContext,accesslog功能都是通过filter来实现了。
  • 在实际业务开发中会对Filter接口进行扩展,在服务调用链路中嵌入我们自身的处理逻辑,如日志打印、调用耗时统计等。

4.3.2 处理器介绍

@Activate(group = PROVIDER, value = ACCESS_LOG_KEY)
public class AccessLogFilter implements Filter {
 
    @Override
    public Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException {
        try {
            if (ConfigUtils.isNotEmpty(accessLogKey)) {
                AccessLogData logData = buildAccessLogData(invoker, inv);
                log(accessLogKey, logData);
            }
        } catch (Throwable t) {
        }
 
        // 执行下一个invoker
        return invoker.invoke(inv);
    }
}

说明:

  • Dubbo中的自定义Filter需要实现org.apache.dubbo.rpc.Filter类,内部通过实现invoke方法来实现自定义逻辑。
  • 自定义Filter内部除了实现必要的自定义逻辑外,核心的需要通过invoker.invoke(inv)触发下一个过滤器的执行。

4.3.3 责任链构建

public class ProtocolFilterWrapper implements Protocol {
 
    private final Protocol protocol;
 
    public ProtocolFilterWrapper(Protocol protocol) {
        this.protocol = protocol;
    }
 
    private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
 
        // 最后的 Invoker 对象
        Invoker<T> last = invoker;
 
        // 遍历所有 Filter 对象,构建责任链         List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
        if (!filters.isEmpty()) {
            for (int i = filters.size() - 1; i >= 0; i--) {
                // 每个 Filter 封装成一个 Invoker 对象,通过 filter.invoke进行串联
                final Filter filter = filters.get(i);
                final Invoker<T> next = last;
                last = new Invoker<T>() {
 
                    @Override
                    public Result invoke(Invocation invocation) throws RpcException {
                        return filter.invoke(next, invocation);
                    }
                };
            }
        }
        return last;
    }
}
 
 
// 封装了Filter的invoker对象
static final class ProtocolFilterWrapper.1 implements Invoker < T > {
    final Invoker val$invoker;
    final Filter val$filter;
    // 指向下一个Invoker的变量
    final Invoker val$next;
 
    public Result invoke(Invocation invocation) throws RpcException {
         return this.val$filter.invoke(this.val$next, invocation);
    }
 
    ProtocolFilterWrapper.1(Invoker invoker, Filter filter, Invoker invoker2) {
        this.val$invoker = invoker;
        this.val$filter = filter;
        this.val$next = invoker2;
    }
}

说明:

  • ProtocolFilterWrapper通过buildInvokerChain构建Dubbo Filter的责任链。
  • 责任链上的处理器对象是将Filter封装的Invoker对象,每个Invoker对象指向下一个处理器封装的Invoker对象。

4.3.4 责任链执行

public class FailfastClusterInvoker<T> extends AbstractClusterInvoker<T> {
 
    public FailfastClusterInvoker(Directory<T> directory) {
        super(directory);
    }
 
    @Override
    public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
        checkInvokers(invokers, invocation);
        Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
        try {
            // 执行封装了Filter的invoker对象,驱动处理器的执行
            return invoker.invoke(invocation);
        } catch (Throwable e) {
             
        }
    }
}
 
static final class ProtocolFilterWrapper.1 implements Invoker < T > {
    final Invoker val$invoker;
    final Filter val$filter;
    final Invoker val$next;
 
    public Result invoke(Invocation invocation) throws RpcException {
         return this.val$filter.invoke(this.val$next, invocation);
    }
 
    ProtocolFilterWrapper.1(Invoker invoker, Filter filter, Invoker invoker2) {
        this.val$invoker = invoker;
        this.val$filter = filter;
        this.val$next = invoker2;
    }

说明:

  • 每个Invoker对象invoke方法会执行自定义逻辑,并触发下一个处理器的执行。
  • 整个责任链上处理器的执行通过Invoker对象的驱动,而非责任链对象的驱动。

4.4 Sentinel

4.4.1 Sentinel Slot介绍

设计模式:诠释抽象责任链模式的实际应用场景

  • Sentinel是面向分布式服务架构的流量治理组件,以流量为切入点提供熔断限流的功能保证系统的稳定性。
  • Sentinel里面以Entry作为限流的资源对象,每个Entry创建的同时会关联一系列功能插槽(slot chain)
  • Sentinel提供了通用的原生Slot处理不同的逻辑,同时支持自定义Slot来定制功能。

4.4.2 处理器介绍

public interface ProcessorSlot<T> {
    void entry(Context context, ResourceWrapper resourceWrapper, T param, int count, boolean prioritized,Object... args) throws Throwable;
    void fireEntry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized,Object... args) throws Throwable;
    void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args);
    void fireExit(Context context, ResourceWrapper resourceWrapper, int count, Object... args);
}
 
public abstract class AbstractLinkedProcessorSlot<T> implements ProcessorSlot<T> {
 
    private AbstractLinkedProcessorSlot<?> next = null;
 
    @Override
    public void fireEntry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized, Object... args)
        throws Throwable {
        // 触发下一个处理器对象的处理
        if (next != null) {
            next.transformEntry(context, resourceWrapper, obj, count, prioritized, args);
        }
    }
 
    void transformEntry(Context context, ResourceWrapper resourceWrapper, Object o, int count, boolean prioritized, Object... args)
        throws Throwable {
        T t = (T)o;
        // 执行具体处理器的逻辑,由具体的处理器自行实现
        entry(context, resourceWrapper, t, count, prioritized, args);
    }
 
    public void setNext(AbstractLinkedProcessorSlot<?> next) {
        // 绑定下一个处理器的逻辑
        this.next = next;
    }
}
 
 
public class NodeSelectorSlot extends AbstractLinkedProcessorSlot<Object> {
 
    private volatile Map<String, DefaultNode> map = new HashMap<String, DefaultNode>(10);
 
    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized, Object... args)
        throws Throwable {
 
        // 1、处理器处理本身的逻辑
        DefaultNode node = map.get(context.getName());
        context.setCurNode(node);
 
        // 2、处理器驱动触发下一个处理器
        fireEntry(context, resourceWrapper, node, count, prioritized, args);
    }
}

说明:

  • Sentinel中的Slot需要实现com.alibaba.csp.sentinel.slotchain.ProcessorSlot的通用接口。
  • 自定义Slot一般继承抽象类 AbstractLinkedProcessorSlot 且只要改写entry/exit`方法实现自定义逻辑。
  • Slot通过next变量保存下一个处理器Slot对象。
  • 在自定义实现的entry方法中需要通过fireEntry触发下一个处理器的执行,在exit方法中通过fireExit 触发下一个处理器的执行。

4.4.3 责任链构建

public class DefaultSlotChainBuilder implements SlotChainBuilder {
 
    @Override
    public ProcessorSlotChain build() {
        // 责任链的头部对象ProcessorSlotChain
        ProcessorSlotChain chain = new DefaultProcessorSlotChain();
 
        // sortedSlotList获取所有的处理器对象
        List<ProcessorSlot> sortedSlotList = SpiLoader.of(ProcessorSlot.class).loadInstanceListSorted();
        for (ProcessorSlot slot : sortedSlotList) {
            if (!(slot instanceof AbstractLinkedProcessorSlot)) {
                continue;
            }
            // 通过尾添法将职责slot添加到DefaultProcessorSlotChain当中
            chain.addLast((AbstractLinkedProcessorSlot<?>) slot);
        }
 
        return chain;
    }
}
 
public class DefaultProcessorSlotChain extends ProcessorSlotChain {
 
    // 创建DefaultProcessorSlotChain的头尾节点first和end
    AbstractLinkedProcessorSlot<?> first = new AbstractLinkedProcessorSlot<Object>() {
 
        @Override
        public void entry(Context context, ResourceWrapper resourceWrapper, Object t, int count, boolean prioritized, Object... args)
            throws Throwable {
            super.fireEntry(context, resourceWrapper, t, count, prioritized, args);
        }
 
        @Override
        public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
            super.fireExit(context, resourceWrapper, count, args);
        }
    };
    AbstractLinkedProcessorSlot<?> end = first;
 
    @Override
    public void addLast(AbstractLinkedProcessorSlot<?> protocolProcessor) {
        end.setNext(protocolProcessor);
        end = protocolProcessor;
    }
}

说明:

  • ProcessorSlotChain作为Slot的责任链,负责责任链的构建和执行。
  • 责任链上的处理器对象AbstractLinkedProcessorSlot通过保存指向下一个处理器的对象的进行关联,整体以链表的形式进行串联。
  • 责任链上的第一个处理器对象first本身不起任何作用,只是保存链表的头部。

4.4.4 责任链执行

public class CtSph implements Sph {
 
    private Entry entryWithPriority(ResourceWrapper resourceWrapper, int count, boolean prioritized, Object... args)
        throws BlockException {
 
        Context context = ContextUtil.getContext();
 
        // 省略相关代码
 
        ProcessorSlot<Object> chain = lookProcessChain(resourceWrapper);
        Entry e = new CtEntry(resourceWrapper, chain, context);
 
        // 驱动责任链上的第一个处理器,进而由处理器自驱动执行下一个处理器
        chain.entry(context, resourceWrapper, null, count, prioritized, args);
         
        return e;
    }
}
 
 
public class DefaultProcessorSlotChain extends ProcessorSlotChain {
 
    // 创建DefaultProcessorSlotChain的头尾节点first和end
    AbstractLinkedProcessorSlot<?> first = new AbstractLinkedProcessorSlot<Object>() {
 
        @Override
        public void entry(Context context, ResourceWrapper resourceWrapper, Object t, int count, boolean prioritized, Object... args)
            throws Throwable {
            super.fireEntry(context, resourceWrapper, t, count, prioritized, args);
        }
 
        @Override
        public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
            super.fireExit(context, resourceWrapper, count, args);
        }
    };
    AbstractLinkedProcessorSlot<?> end = first;
 
    @Override
    public void addLast(AbstractLinkedProcessorSlot<?> protocolProcessor) {
        end.setNext(protocolProcessor);
        end = protocolProcessor;
    }
}
 
public abstract class AbstractLinkedProcessorSlot<T> implements ProcessorSlot<T> {
  
    private AbstractLinkedProcessorSlot<?> next = null;
  
    @Override
    public void fireEntry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized, Object... args)
        throws Throwable {
        // 触发下一个处理器对象的处理
        if (next != null) {
            next.transformEntry(context, resourceWrapper, obj, count, prioritized, args);
        }
    }
  
    void transformEntry(Context context, ResourceWrapper resourceWrapper, Object o, int count, boolean prioritized, Object... args)
        throws Throwable {
        T t = (T)o;
        // 执行具体处理器的逻辑,由具体的处理器自行实现
        entry(context, resourceWrapper, t, count, prioritized, args);
    }
  
    public void setNext(AbstractLinkedProcessorSlot<?> next) {
        // 绑定下一个处理器的逻辑
        this.next = next;
    }
}

说明:

  • 整个责任链上处理器的执行通过Invoker对象的驱动,而非责任链对象的驱动。
  • DefaultProcessorSlotChainentry首先头部对象first,进而触发处理器的自驱实现处理器的执行。
  • 整体按照entry → fireEntry → transformEntry → entry的循环顺序依次触发处理器的自驱。

五、总结

责任链模式是一种强大而灵活的设计模式,它可以帮助我们构建具有可扩展性和低耦合度的处理流程。通过将请求发送方和接收方解耦,责任链模式允许我们动态地改变或扩展请求的处理顺序,从而实现更高度的灵活性和可维护性。

责任链模式的优点在于其低耦合性、灵活性和可扩展性,使得我们能够更加轻松地管理和组织复杂的处理流程。然而,也要注意其缺点,即请求未必被处理和对处理顺序敏感的特点。

最重要的是,在实际应用中根据具体需求合理运用责任链模式,结合其他设计模式,以便在代码结构和可维护性上取得更好的效果。本文主要是通过一个责任链模式模板和具体实战代码以及通过分析一些优秀框架的设计源码来诠释什么是《责任链模式》,好了,今天的分享就到此结束了,如果文章对你有所帮助,欢迎:点赞👍+评论💬+收藏❤,我是:IT_sunshine,我们下期见!

参考:

转载自:https://juejin.cn/post/7338269539539402779
评论
请登录