在GoF 的《設(shè)計(jì)模式》一書中對(duì)責(zé)任鏈模定義的:將請(qǐng)求的發(fā)送和接收解耦,讓多個(gè)接收對(duì)象都有機(jī)會(huì)處理這個(gè)請(qǐng)求。將這些接收對(duì)象串成一條鏈,并沿著這條鏈傳遞這個(gè)請(qǐng)求,直到鏈上的某個(gè)接收對(duì)象能夠處理它為止或者所有接收對(duì)象處理一遍。 用通俗的話解釋在責(zé)任鏈模式中,多個(gè)處理器(接收對(duì)象)依次處理同一個(gè)請(qǐng)求。一個(gè)請(qǐng)求先經(jīng)過(guò) A 處理器處理,然后再把請(qǐng)求傳遞給 B 處理器,B 處理器處理完后再傳遞給 C 處理器,以此類推,形成一個(gè)鏈條。鏈條上的每個(gè)處理器各自承擔(dān)各自的處理職責(zé),所以叫作責(zé)任鏈模式。 責(zé)任鏈模式有效地降低了發(fā)送和接收者之間的耦合度,增強(qiáng)了系統(tǒng)的可擴(kuò)展性。在責(zé)任鏈的模式下不僅能夠針對(duì)單個(gè)處理器對(duì)象進(jìn)行定制升級(jí)(每個(gè)處理器對(duì)象關(guān)注各自的任務(wù)),而且能夠?qū)φ麄€(gè)責(zé)任鏈的處理器對(duì)象的順序的調(diào)整以及增刪。 本文約定:責(zé)任鏈上的接收對(duì)象統(tǒng)一稱為處理器;本文中介紹的責(zé)任鏈屬于GOF定義中責(zé)任鏈的變種即責(zé)任鏈上的所有處理器都會(huì)參與任務(wù)的處理。 責(zé)任鏈模式有多種實(shí)現(xiàn)方式,從驅(qū)動(dòng)責(zé)任鏈上處理器方式的角度可以分類兩類,即責(zé)任鏈驅(qū)動(dòng) 和 責(zé)任鏈處理器自驅(qū)動(dòng)。 說(shuō)明: 說(shuō)明: 責(zé)任鏈低耦合高擴(kuò)展的特點(diǎn)讓它在很多開源的框架中被采用,本文選取了開源框架中的Spring Interceptor、Servlet Filter、Dubbo、Sentinel進(jìn)行責(zé)任鏈的實(shí)現(xiàn)介紹,通過(guò)對(duì)常用框架中責(zé)任鏈應(yīng)用的了解能夠更好掌握責(zé)任鏈落地并在日常的開發(fā)中積極的使用。 3.1.1 Interceptor介紹 圖片 3.1.2 處理器介紹 說(shuō)明: 3.1.3 責(zé)任鏈構(gòu)建 說(shuō)明: 3.1.4 責(zé)任鏈執(zhí)行 說(shuō)明: 3.2.1 Filter介紹 3.2.2 處理器介紹 說(shuō)明: 3.2.3 責(zé)任鏈構(gòu)建 說(shuō)明: 3.2.4 責(zé)任鏈執(zhí)行 說(shuō)明: 3.3.1 Dubbo Filter介紹 3.3.2 處理器介紹 說(shuō)明: 3.3.3 責(zé)任鏈構(gòu)建 說(shuō)明: 3.3.4 責(zé)任鏈執(zhí)行 說(shuō)明: 3.4.1 Sentinel Slot介紹 3.4.2 處理器介紹 說(shuō)明: 3.4.3 責(zé)任鏈構(gòu)建 說(shuō)明: 3.4.4 責(zé)任鏈執(zhí)行 說(shuō)明: 在日常項(xiàng)目實(shí)踐中,責(zé)任鏈的設(shè)計(jì)模式會(huì)在很多業(yè)務(wù)場(chǎng)景中落地。 譬如對(duì)于支持用戶生成內(nèi)容(UGC)的應(yīng)用來(lái)說(shuō),用戶生成的內(nèi)容可能包含一些敏感內(nèi)容如敏感言論或者圖片等。針對(duì)這種應(yīng)用場(chǎng)景,可以通過(guò)責(zé)任鏈模式設(shè)置多個(gè)處理器來(lái)處理不同的任務(wù),如文本過(guò)濾器處理敏感詞,圖片過(guò)濾器處理敏感圖片等等。 譬如對(duì)于電商服務(wù)中的下單流程來(lái)說(shuō),一個(gè)下單流程包含訂單拆合單,優(yōu)惠計(jì)算,訂單生成等多個(gè)步驟,我們可以通過(guò)責(zé)任鏈模式設(shè)置多個(gè)處理器來(lái)處理不同的任務(wù)等等。 責(zé)任鏈的應(yīng)用場(chǎng)景非常廣泛,在常見的開源框架中有豐富的落地場(chǎng)景,同樣在業(yè)務(wù)開發(fā)中也可以根據(jù)場(chǎng)景靈活使用。 一、責(zé)任鏈介紹
二、責(zé)任鏈實(shí)現(xiàn)
2.1 處理器自驅(qū)動(dòng)
// 1、定義抽象類
public abstract class AbstractHandler {
protected Handler next = null;
// 綁定處理器
public void setSuccessor(Handler next) {
this.next = next;
}
// 處理器執(zhí)行操作并驅(qū)動(dòng)下一個(gè)處理器
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、構(gòu)建責(zé)任鏈并添加處理器
public class HandlerChAIn {
// 通過(guò)鏈表的形式保存責(zé)任鏈
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、整體構(gòu)建責(zé)任鏈添加處理器并進(jìn)行驅(qū)動(dòng)
public class Application {
public static void main(String[] args) {
// 構(gòu)建責(zé)任鏈并添加處理器
HandlerChain chain = new HandlerChain();
chain.addHandler(new HandlerA());
chain.addHandler(new HandlerB());
// 責(zé)任鏈負(fù)責(zé)觸發(fā)
chain.handle();
}
}
2.2 責(zé)任鏈驅(qū)動(dòng)
// 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、構(gòu)建責(zé)任鏈并添加處理器
public class HandlerChain {
// 通過(guò)數(shù)組的形式保存處理器
private List<IHandler> handlers = new ArrayList<>();
public void addHandler(IHandler handler) {
handlers.add(handler);
}
// 由責(zé)任鏈負(fù)責(zé)遍歷所有的處理器并進(jìn)行調(diào)用
public void handle() {
for (IHandler handler : handlers) {
handler.handle();
}
}
}
// 5、整體構(gòu)建責(zé)任鏈添加處理器并進(jìn)行驅(qū)動(dòng)
public class Application {
public static void main(String[] args) {
HandlerChain chain = new HandlerChain();
chain.addHandler(new HandlerA());
chain.addHandler(new HandlerB());
chain.handle();
}
}
三、開源框架中責(zé)任鏈應(yīng)用
3.1 Spring Interceptor
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");
}
}
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;
}
}
public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
try {
// mappedHandler代表的是HandlerExecutionChain責(zé)任鏈 mappedHandler = getHandler(processedRequest);
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 1、執(zhí)行mappedHandler的applyPreHandle方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 2、執(zhí)行controller的執(zhí)行邏輯
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
// 執(zhí)行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)) {
// 責(zé)任鏈從前往后的順序執(zhí)行
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)) {
// 責(zé)任鏈從后往前的順序執(zhí)行
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
}
3.2 Servlet Filter
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、執(zhí)行處理的邏輯
System.out.println("time filter doFilter");
// 2、執(zhí)行責(zé)任鏈當(dāng)中的下一個(gè) Filter 對(duì)象,等價(jià)于執(zhí)行 FilterChain 的internalDoFilter方法
filterChain.doFilter(servletRequest, servletResponse);
}
}
public final class ApplicationFilterChain implements FilterChain {
// 責(zé)任鏈上 Filter 的維護(hù)對(duì)象
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
//責(zé)任鏈上待執(zhí)行的 Filter 對(duì)象
private int pos = 0;
// 責(zé)任鏈上擁有的 Filter 數(shù)量
private int n = 0;
void addFilter(ApplicationFilterConfig filterConfig) {
// 避免重復(fù)添加Filter
for(ApplicationFilterConfig filter:filters)
if(filter==filterConfig)
return;
// 按需進(jìn)行擴(kuò)容
if (n == filters.length) {
ApplicationFilterConfig[] newFilters =
new ApplicationFilterConfig[n + INCREMENT];
System.arraycopy(filters, 0, newFilters, 0, n);
filters = newFilters;
}
// 保存Filter 對(duì)象
filters[n++] = filterConfig;
}
}
public final class ApplicationFilterChain implements FilterChain {
// 責(zé)任鏈上 Filter 的維護(hù)對(duì)象
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
//責(zé)任鏈上待執(zhí)行的 Filter 對(duì)象
private int pos = 0;
// 責(zé)任鏈上擁有的 Filter 數(shù)量
private int n = 0;
// 責(zé)任鏈的執(zhí)行
private void internalDoFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
// 在責(zé)任鏈未執(zhí)行完的情況下執(zhí)行責(zé)任鏈 if (pos < n) {
// 獲取當(dāng)前待執(zhí)行的 Filter,同時(shí)遞增下一次待執(zhí)行責(zé)任鏈的下標(biāo)
ApplicationFilterConfig filterConfig = filters[pos++];
try {
Filter filter = filterConfig.getFilter();
if( Globals.IS_SECURITY_ENABLED ) {
// 省略相關(guān)代碼
} else {
filter.doFilter(request, response, this);
}
} catch (Throwable e) {
}
return;
}
try {
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse) &&
Globals.IS_SECURITY_ENABLED ) {
// 執(zhí)行正常的業(yè)務(wù)邏輯
} else {
servlet.service(request, response);
}
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
throw new ServletException(sm.getString("filterChain.servlet"), e);
}
}
}
(servletRequest, servletResponse)觸發(fā)下一個(gè)處理器的執(zhí)行。3.3 Dubbo
@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) {
}
// 執(zhí)行下一個(gè)invoker
return invoker.invoke(inv);
}
}
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 對(duì)象
Invoker<T> last = invoker;
// 遍歷所有 Filter 對(duì)象,構(gòu)建責(zé)任鏈 List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
if (!filters.isEmpty()) {
for (int i = filters.size() - 1; i >= 0; i--) {
// 每個(gè) Filter 封裝成一個(gè) Invoker 對(duì)象,通過(guò) filter.invoke進(jìn)行串聯(lián)
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對(duì)象
static final class ProtocolFilterWrapper.1 implements Invoker < T > {
final Invoker val$invoker;
final Filter val$filter;
// 指向下一個(gè)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;
}
}
buildInvokerChain構(gòu)建Dubbo Filter的責(zé)任鏈。
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 {
// 執(zhí)行封裝了Filter的invoker對(duì)象,驅(qū)動(dòng)處理器的執(zhí)行
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;
}
3.4 Sentinel
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 {
// 觸發(fā)下一個(gè)處理器對(duì)象的處理
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;
// 執(zhí)行具體處理器的邏輯,由具體的處理器自行實(shí)現(xiàn)
entry(context, resourceWrapper, t, count, prioritized, args);
}
public void setNext(AbstractLinkedProcessorSlot<?> next) {
// 綁定下一個(gè)處理器的邏輯
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、處理器驅(qū)動(dòng)觸發(fā)下一個(gè)處理器
fireEntry(context, resourceWrapper, node, count, prioritized, args);
}
}
com.alibaba.csp.sentinel.slotchain.ProcessorSlot的通用接口。
public class DefaultSlotChainBuilder implements SlotChainBuilder {
@Override
public ProcessorSlotChain build() {
// 責(zé)任鏈的頭部對(duì)象ProcessorSlotChain
ProcessorSlotChain chain = new DefaultProcessorSlotChain();
// sortedSlotList獲取所有的處理器對(duì)象
List<ProcessorSlot> sortedSlotList = SpiLoader.of(ProcessorSlot.class).loadInstanceListSorted();
for (ProcessorSlot slot : sortedSlotList) {
if (!(slot instanceof AbstractLinkedProcessorSlot)) {
continue;
}
// 通過(guò)尾添法將職責(zé)slot添加到DefaultProcessorSlotChain當(dāng)中
chain.addLast((AbstractLinkedProcessorSlot<?>) slot);
}
return chain;
}
}
public class DefaultProcessorSlotChain extends ProcessorSlotChain {
// 創(chuàng)建DefaultProcessorSlotChain的頭尾節(jié)點(diǎn)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;
}
}
AbstractLinkedProcessorSlot通過(guò)保存指向下一個(gè)處理器的對(duì)象的進(jìn)行關(guān)聯(lián),整體以鏈表的形式進(jìn)行串聯(lián)。
public class CtSph implements Sph {
private Entry entryWithPriority(ResourceWrapper resourceWrapper, int count, boolean prioritized, Object... args)
throws BlockException {
Context context = ContextUtil.getContext();
// 省略相關(guān)代碼
ProcessorSlot<Object> chain = lookProcessChain(resourceWrapper);
Entry e = new CtEntry(resourceWrapper, chain, context);
// 驅(qū)動(dòng)責(zé)任鏈上的第一個(gè)處理器,進(jìn)而由處理器自驅(qū)動(dòng)執(zhí)行下一個(gè)處理器
chain.entry(context, resourceWrapper, null, count, prioritized, args);
return e;
}
}
public class DefaultProcessorSlotChain extends ProcessorSlotChain {
// 創(chuàng)建DefaultProcessorSlotChain的頭尾節(jié)點(diǎn)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 {
// 觸發(fā)下一個(gè)處理器對(duì)象的處理
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;
// 執(zhí)行具體處理器的邏輯,由具體的處理器自行實(shí)現(xiàn)
entry(context, resourceWrapper, t, count, prioritized, args);
}
public void setNext(AbstractLinkedProcessorSlot<?> next) {
// 綁定下一個(gè)處理器的邏輯
this.next = next;
}
}
transformEntry→ entry的循環(huán)順序依次觸發(fā)處理器的自驅(qū)。四、實(shí)踐總結(jié)
開源框架中的責(zé)任鏈模式實(shí)踐
網(wǎng)友整理
注冊(cè)時(shí)間:
網(wǎng)站:5 個(gè) 小程序:0 個(gè) 文章:12 篇
-
51998
網(wǎng)站
- 12
小程序
-
1030137
文章
-
747
會(huì)員
文章分類
熱門網(wǎng)站
- 各百科-專業(yè)百科問(wèn)答知識(shí)名網(wǎng)站 m.geelcn.com
- 免費(fèi)軟件,綠色軟件園,手機(jī)軟件下載,熱門游戲下載中心-中當(dāng)網(wǎng) m.deelcn.com
- 魔扣科技 www.ylptlb.cn
- 體育新聞_國(guó)際體育資訊_全球體育賽事-中名網(wǎng) www.feelcn.com/tiyu/tiyuxinwen/
- 食品安全_健康飲食_舌尖上的安全-中名網(wǎng) www.feelcn.com/shenghuo/shipinanquan/
- 中合網(wǎng) www.heelcn.com
- 中當(dāng)網(wǎng) www.deelcn.com
- 魔扣網(wǎng)站維護(hù)代運(yùn)營(yíng) www.ylptlb.cn/tg
- 中合網(wǎng)-健康養(yǎng)生知識(shí)科普名站 m.heelcn.com
- 各百科 www.geelcn.com
最新入駐小程序
數(shù)獨(dú)大挑戰(zhàn)2018-06-03
數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9
答題星2018-06-03
您可以通過(guò)答題星輕松地創(chuàng)建試卷
全階人生考試2018-06-03
各種考試題,題庫(kù),初中,高中,大學(xué)四六
運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03
記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷
每日養(yǎng)生app2018-06-03
每日養(yǎng)生,天天健康
體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03
通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定
熱門文章
- 民以食為天 離線人臉識(shí)別助力打造智慧食堂 08-20
- 青桔單車發(fā)布3款新車 已進(jìn)入150個(gè)城市 08-13
- 民間大神用Win7毛玻璃UI風(fēng)格改造Win10:情懷滿滿 08-06
- 網(wǎng)站標(biāo)題是否可以修改?怎么改不影響網(wǎng)站權(quán)重? 11-19
- 關(guān)于網(wǎng)站標(biāo)題和正文的匹配度分析 09-29
- 從滾石、華納到環(huán)球,三個(gè)關(guān)鍵詞讀懂網(wǎng)易云為何成版權(quán)方最愛 08-12
- 天眼被注冊(cè)為煙草商標(biāo),中國(guó)控?zé)焻f(xié)會(huì)要求嚴(yán)查 08-13
- 深圳實(shí)現(xiàn)5G獨(dú)立組網(wǎng)全覆蓋 已累計(jì)建設(shè)5G基站超4.6萬(wàn)個(gè) 08-17
- 滴滴App內(nèi)嵌買車服務(wù) 已在十余城上線 08-06
- 關(guān)鍵詞的密度要結(jié)合頁(yè)面版式來(lái)調(diào)整 11-28