作者:vivo 互联网服务器团队 -Wang Zhi
责任链模式作为罕用的设计模式而被大家熟知和应用。本文介绍责任链的常见实现形式,并联合开源框架如 Dubbo、Sentinel 等进行延长探讨。
一、责任链介绍
在 GoF 的《设计模式》一书中对责任链模定义的:将申请的发送和接管解耦,让多个接管对象都有机会解决这个申请。将这些接管对象串成一条链,并沿着这条链传递这个申请,直到链上的某个接管对象可能解决它为止或者所有接管对象解决一遍。
用艰深的话解释在责任链模式中,多个处理器(接管对象)顺次解决同一个申请。一个申请先通过 A 处理器解决,而后再把申请传递给 B 处理器,B 处理器解决完后再传递给 C 处理器,以此类推,造成一个链条。链条上的每个处理器各自承当各自的解决职责,所以叫作责任链模式。
责任链模式无效地升高了发送和接收者之间的耦合度,加强了零碎的可扩展性。在责任链的模式下不仅可能针对单个处理器对象进行定制降级(每个处理器对象关注各自的工作),而且可能对整个责任链的处理器对象的程序的调整以及增删。
本文约定:责任链上的接管对象对立称为 处理器 ;本文中介绍的责任链属于 GOF 定义中责任链的变种即 责任链上的所有处理器都会参加工作的解决。
二、责任链实现
责任链模式有多种实现形式,从驱动责任链上处理器形式的角度能够分类两类,即 责任链驱动 和 责任链处理器自驱动。
2.1 处理器自驱动
// 1、定义抽象类
public abstract class AbstractHandler {
protected Handler next = null;
// 绑定处理器
public void setSuccessor(Handler next) {this.next = next;}
// 处理器执行操作并驱动下一个处理器
public abstract void handle();}
// 2、定义处理器 A
public class HandlerA extends AbstractHandler {
@Override
public void handle() {
// do something
if (next != null) {next.handle();
}
}
}
// 3、定义处理器 B
public class HandlerB extends AbstractHandler {
@Override
public void handle() {
// do something
if (next != null) {next.handle();
}
}
}
// 4、构建责任链并增加处理器
public class HandlerChain {
// 通过链表的模式保留责任链
private AbstractHandler head = null;
private AbstractHandler tail = null;
public void addHandler(AbstractHandler handler) {handler.setSuccessor(null);
if (head == null) {
head = handler;
tail = handler;
return;
}
tail.setSuccessor(handler);
tail = handler;
}
public void handle() {if (head != null) {head.handle();
}
}
}
// 5、整体构建责任链增加处理器并进行驱动
public class Application {public static void main(String[] args) {
// 构建责任链并增加处理器
HandlerChain chain = new HandlerChain();
chain.addHandler(new HandlerA());
chain.addHandler(new HandlerB());
// 责任链负责触发
chain.handle();}
}
阐明:
- 责任链上的每个处理器对象保护下一个处理器对象,整个责任链的驱动由每个处理器对象自行驱动。
- 每个处理器对象 Handler 中蕴含下一个处理器对象 next 的变量,通过链表模式保护责任链的关系。
2.2 责任链驱动
// 1、定义形象接口
public interface IHandler {void doSomething();
}
// 2、定义处理器 A
public class HandlerA implements IHandler {
@Override
public void doSomething() {// do something}
}
// 3、定义处理器 B
public class HandlerB implements IHandler {
@Override
public void doSomething() {// do something}
}
// 4、构建责任链并增加处理器
public class HandlerChain {
// 通过数组的模式保留处理器
private List<IHandler> handlers = new ArrayList<>();
public void addHandler(IHandler handler) {handlers.add(handler);
}
// 由责任链负责遍历所有的处理器并进行调用
public void handle() {for (IHandler handler : handlers) {handler.handle();
}
}
}
// 5、整体构建责任链增加处理器并进行驱动
public class Application {public static void main(String[] args) {HandlerChain chain = new HandlerChain();
chain.addHandler(new HandlerA());
chain.addHandler(new HandlerB());
chain.handle();}
}
阐明:
- 责任链对象自身以数组的模式保护处理器对象,即上述代码中的 handlers。
- 责任链的处理器的执行由责任链对象循环调用处理器对象驱动,即上述代码中的 handle 办法。
三、开源框架中责任链利用
责任链低耦合高扩大的特点让它在很多开源的框架中被采纳,本文选取了开源框架中的 Spring Interceptor、Servlet Filter、Dubbo、Sentinel 进行责任链的实现介绍,通过对罕用框架中责任链利用的理解可能更好把握责任链落地并在日常的开发中踊跃的应用。
3.1 Spring Interceptor
3.1.1 Interceptor 介绍
- Spring 中的拦截器(Interceptor) 用于拦挡控制器办法的执行,能够在办法执行前后增加自定义逻辑相似于 AOP 编程思维。
- Inteceptor 的作用机会是在申请(request)进入 servlet 后,在进入 Controller 之前进行预处理。
- Inteceptor 的理论利用包含:认证受权、日志记录、字符编码转换,敏感词过滤等等。
- Inteceptor 中责任链的实现会从处理器的介绍,责任链的构建以及责任链的执行三个角度进行论述。
3.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 类实现的责任链上。
3.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 保留所有相干的处理器对象。
3.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);
}
}
}
}
阐明:
- 在 servlet 的 doDispatch 办法中顺次触发责任链的 applyPreHandle 的前置解决办法、applyPostHandle 的后置解决办法。
- 前置解决办法 applyPreHandle 会遍历责任链上的处理器从前往后顺次解决,后置解决办法 applyPostHandle 会遍历责任链上的处理器从后往前顺次解决。
- 处理器的驱动由责任链对象负责顺次触发,非处理器对象自驱执行。
3.2 Servlet Filter
3.2.1 Filter 介绍
- Servlet 过滤器是在 Java Servlet 标准 2.3 中定义的,它可能对 Servlet 容器的申请和响应对象进行检查和批改,是个典型的责任链。
- 在 Servlet 被调用之前查看 Request 对象并反对批改 Request Header 和 Request 内容。
- 在 Servlet 被调用之后查看 Response 对象并支批改 Response Header 和 Response 内容。
3.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 容器在销毁过滤器实例前调用该办法,能够开释过滤器占用的资源。
3.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 来实现。
3.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) 触发下一个处理器的执行。
3.3 Dubbo
3.3.1 Dubbo Filter 介绍
图片分享自《DUBBO 官网》
- Dubbo 的 Filter 作用机会如上图所示,Filter 实现是专门为服务提供方和服务生产方调用过程进行拦挡,Dubbo 自身的大多功能均基于此扩大点实现,每次近程办法执行该拦挡都会被执行。
- Dubbo 官网针对 Filter 做了很多的原生反对,目前大抵有 20 来个吧,包含咱们熟知的 RpcContext,accesslog 性能都是通过 filter 来实现了。
- 在理论业务开发中会对 Filter 接口进行扩大,在服务调用链路中嵌入咱们本身的解决逻辑,如日志打印、调用耗时统计等。
3.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)触发下一个过滤器的执行。
3.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 对象。
3.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 对象的驱动,而非责任链对象的驱动。
3.4 Sentinel
3.4.1 Sentinel Slot 介绍
图片分享自《Sentinel 官网》
- Sentinel 是面向分布式服务架构的流量治理组件,以流量为切入点提供熔断限流的性能保证系统的稳定性。
- Sentinel 外面以 Entry 作为限流的资源对象,每个 Entry 创立的同时会关联一系列性能插槽(slot chain)。
- Sentinel 提供了通用的原生 Slot 解决不同的逻辑,同时反对自定义 Slot 来定制性能。
3.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 触发下一个处理器的执行。
3.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 自身不起任何作用,只是保留链表的头部。
3.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 对象的驱动,而非责任链对象的驱动。
- DefaultProcessorSlotChain 的 entry 首先头部对象 first,进而触发处理器的自驱实现处理器的执行。
- 整体依照 entry → fireEntry → transformEntry → entry 的循环程序顺次触发处理器的自驱。
四、实际总结
在日常我的项目实际中,责任链的设计模式会在很多业务场景中落地。
譬如对于反对用户生成内容(UGC)的利用来说,用户生成的内容可能蕴含一些敏感内容如敏感舆论或者图片等。针对这种利用场景,能够通过责任链模式设置多个处理器来解决不同的工作,如文本过滤器解决敏感词,图片过滤器解决敏感图片等等。
譬如对于电商服务中的下单流程来说,一个下单流程蕴含订单拆合单,优惠计算,订单生成等多个步骤,咱们能够通过责任链模式设置多个处理器来解决不同的工作等等。
责任链的利用场景十分宽泛,在常见的开源框架中有丰盛的落地场景,同样在业务开发中也能够依据场景灵便应用。