I. 責任の連鎖の概要GoFの書籍『デザインパターン』で定義されているChain of Responsibilityパターンは、リクエストの送信と受信を分離し、複数の受信オブジェクトがリクエストを処理できるようにします。これらの受信オブジェクトは連鎖的に接続され、リクエストはいずれかの受信オブジェクトが処理できるようになるまで、またはすべての受信オブジェクトが処理し終わるまで、チェーンに沿って渡されます。 簡単に言えば、「Chain of Responsibility」パターンとは、複数のハンドラー(受信オブジェクト)が同じリクエストを順番に処理することを意味します。リクエストはまずハンドラーAによって処理され、次にハンドラーB、ハンドラーCへと渡され、このようにチェーンを形成します。チェーン内の各ハンドラーはそれぞれ独自の処理責任を担うため、「Chain of Responsibility」という名前が付けられています。 Chain of Responsibilityパターンは、送信側と受信側の結合を効果的に低減し、システムのスケーラビリティを向上させます。このパターンでは、個々のハンドラーオブジェクト(各ハンドラーはそれぞれのタスクに集中)のカスタマイズとアップグレードだけでなく、チェーン全体にわたるハンドラーオブジェクトの順序調整や追加・削除も可能になります。 この記事では、責任の連鎖上の受信オブジェクトをまとめてプロセッサと呼ぶことにします。この記事で紹介する責任の連鎖は、責任の連鎖上のすべてのプロセッサがタスクの処理に参加するという点で、GOF で定義された責任の連鎖の変形です。 II. 責任の連鎖の実施Chain of Responsibilityパターンの実装方法は複数あります。Chain of Responsibility上のプロセッサがどのように駆動されるかという観点から、 Chain of Responsibility駆動型とChain of Responsibilityプロセッサ自己駆動型の2つのカテゴリに分類できます。 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(); } }
例: - Chain of Responsibility オブジェクト自体は、ハンドラー オブジェクトを配列として保持します (上記のコードでは handlers)。
- 責任チェーン内のハンドラーの実行は、ループ内でハンドラー オブジェクトを呼び出す責任チェーン オブジェクト (つまり、上記のコードの handle メソッド) によって実行されます。
III. オープンソースフレームワークにおける責任連鎖の適用Chain of Responsibilityは、その疎結合性と高いスケーラビリティにより、多くのオープンソースフレームワークで採用されています。この記事では、Spring Interceptor、Servlet Filter、Dubbo、SentinelといったオープンソースフレームワークにおけるChain of Responsibilityの実装を紹介します。一般的なフレームワークにおけるChain of Responsibilityの適用方法を理解することで、実装をより深く理解し、日々の開発で積極的に活用できるようになります。 3.1 スプリングインターセプター3.1.1 インターセプターの紹介
写真 - Spring では、インターセプターを使用してコントローラー メソッドの実行をインターセプトし、AOP プログラミング パラダイムと同様に、メソッド実行の前後にカスタム ロジックを追加できます。
- Inteceptor は、リクエストがサーブレットに入った後、コントローラに入る前にリクエストを前処理するために使用されます。
- Inteceptor の実用的なアプリケーションには、認証と承認、ログ記録、文字エンコード変換、機密単語のフィルタリングなどがあります。
- Inteceptor における責任連鎖の実装について、プロセッサの導入、責任連鎖の構築、責任連鎖の実行という 3 つの観点から説明します。
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"); } }
例: - プロセッサ インターセプターの HandlerInterceptor インターフェイスは、コントローラー メソッドの実行の前後にカスタム ロジックを追加できる 3 つのメソッドを定義します。
- 上記の 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 クラスは、インターセプター プロセッサを接続する責任のチェーンとして機能し、チェーンの構築と実行を担当します。
- 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); } } } }
例: - サーブレットの doDispatch メソッドでは、責任連鎖の前処理メソッド applyPreHandle と後処理メソッド applyPostHandle が順番にトリガーされます。
- 前処理メソッド applyPreHandle は、責任のチェーン内のプロセッサを反復処理し、前から後ろへ順番に処理します。一方、後処理メソッド applyPostHandle は、責任のチェーン内のプロセッサを反復処理し、後ろから前へ順番に処理します。
- プロセッサのドライブは責任オブジェクトのチェーンによって順番にトリガーされ、非プロセッサ オブジェクトは独自のドライブを実行します。
3.2 サーブレットフィルタ3.2.1 フィルタの概要 - サーブレットフィルタはJavaサーブレット仕様2.3で定義されています。サーブレットコンテナのリクエストオブジェクトとレスポンスオブジェクトを検査および変更することができ、典型的な責任連鎖です。
- サーブレットが呼び出される前にリクエスト オブジェクトが検査され、リクエスト ヘッダーとリクエスト コンテンツの変更がサポートされます。
- サーブレットが呼び出された後、レスポンス オブジェクトが検査され、レスポンス ヘッダーとレスポンス コンテンツが変更されます。
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); } }
例: - サーブレット フィルタ クラスは、3 つの共通メソッドを定義する javax.servlet.Filter インターフェイスを実装する必要があります。
- `init` メソッドはサーブレットフィルタの初期化を担います。このメソッドは、サーブレットフィルタインスタンスの作成時にサーブレットコンテナによって呼び出されます。
- クライアントがフィルターに関連付けられた URL へのアクセスを要求すると、サーブレット コンテナによって `doFilter` メソッドが呼び出されます。
- destroy メソッド: サーブレット コンテナは、フィルタ インスタンスを破棄する前にこのメソッドを呼び出して、フィルタによって占有されているリソースを解放します。
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 はフィルターの責任チェーンとして機能し、フィルターの構築と実行を担当します。
- 責任の連鎖は、フィルターと呼ばれる ApplicationFilterConfig タイプのオブジェクトの配列を通じてフィルター ハンドラーを格納します。
- 責任の連鎖へのプロセッサの追加は、それらを配列フィルターに保存することによって実現されます。
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); } } }
例: - 責任チェーン全体にわたるフィルター プロセッサの実行は、責任チェーン オブジェクトによって駆動されるのではなく、プロセッサの自己駆動によって実現されます。
- フィルター プロセッサは、独自のロジックを実行するだけでなく、処理中にfilterChain.doFilterも使用します。
(servletRequest、servletResponse) は次のハンドラーの実行をトリガーします。
3.3 ダボ3.3.1 Dubboフィルターの紹介 - 上の図に示すように、Dubboのフィルターは、サービスプロバイダーとコンシューマー間の呼び出しをインターセプトするために特別に設計されています。Dubboの機能のほとんどはこの拡張ポイントに基づいており、このインターセプションはリモートメソッドが実行されるたびに実行されます。
- Dubbo は、フィルターを通じて実装される RpcContext や accesslog などのよく知られた機能を含め、現在約 20 個のフィルターに対してネイティブ サポートを多数提供しています。
- 実際のビジネス開発では、フィルター インターフェイスを拡張して、ログの印刷や呼び出し時間の統計など、独自の処理ロジックをサービス呼び出しチェーンに組み込みます。
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 のカスタム フィルターでは、カスタム ロジックを実現するために invoke メソッドを内部的に実装する org.apache.dubbo.rpc.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 フィルターの責任チェーンを構築します。 - 責任の連鎖におけるプロセッサ オブジェクトは、フィルターをカプセル化する 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 センチネル3.4.1 センチネルスロットの紹介 - Sentinelは、分散サービスアーキテクチャ向けのトラフィックガバナンスコンポーネントです。トラフィックに基づいてサーキットブレーキングとレート制限機能を提供し、システムの安定性を確保します。
- Sentinelでは、Entryはレート制限のためのリソースオブジェクトとして使用されます。各Entryは、作成時に一連の関数スロットに関連付けられます。
- Sentinel は、さまざまなロジックを処理するための一般的なネイティブ スロットを提供するとともに、機能をカスタマイズするためのカスタム スロットもサポートしています。
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 のスロットを実装する必要があります。
com.alibaba.csp.sentinel.slotchain.ProcessorSlot の汎用インターフェイス。 - カスタム スロットは通常、抽象クラス AbstractLinkedProcessorSlot から継承され、カスタム ロジックを実装するにはエントリ/終了メソッドを書き直すだけで済みます。
- スロットは、次の変数を通じて次のプロセッサ スロット オブジェクトを格納します。
- エントリ メソッドのカスタム実装では、次のプロセッサの実行を fireEntry によってトリガーする必要があり、終了メソッドでは、次のプロセッサの実行を 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 は、スロットの責任チェーンとして機能し、責任チェーンの構築と実行を担当します。
- 責任の連鎖におけるプロセッサオブジェクト
AbstractLinkedProcessorSlot は、次のプロセッサを指すオブジェクトを格納することによってリンクされており、全体がリンク リストの形式で接続されています。 - 責任連鎖の最初のハンドラー オブジェクト自体は何の役割も果たさず、リンク リストの先頭を格納するだけです。
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 → fireEntry →
transformEntry → entry のループシーケンスは、プロセッサの自動駆動機構を順次起動します。
IV. 実践の要約日常的なプロジェクトの実践では、責任の連鎖設計パターンが多くのビジネス シナリオに適用されます。 例えば、ユーザー生成コンテンツ(UGC)をサポートするアプリケーションでは、ユーザー生成コンテンツにセンシティブな発言や画像などの機密情報が含まれる場合があります。このようなアプリケーションでは、責任連鎖パターンを使用して、センシティブな単語を処理するテキストフィルター、センシティブな画像を処理する画像フィルターなど、複数のプロセッサを異なるタスクごとに設定することができます。 例えば、eコマースサービスの発注プロセスでは、注文の分割と統合、割引計算、注文の生成など、複数のステップが含まれます。Chain of Responsibilityパターンを使用することで、複数のプロセッサを設定し、異なるタスクなどを処理することができます。 Chain of Responsibilityは応用範囲が広く、一般的なオープンソースフレームワークにも多数の実装シナリオがあり、ビジネス開発においてもシナリオに応じて柔軟に活用できます。 |