溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

責(zé)任鏈模式如何在Java項(xiàng)目中實(shí)現(xiàn)

發(fā)布時(shí)間:2020-12-04 16:49:04 來(lái)源:億速云 閱讀:199 作者:Leah 欄目:編程語(yǔ)言

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)責(zé)任鏈模式如何在Java項(xiàng)目中實(shí)現(xiàn),文章內(nèi)容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

責(zé)任鏈模式

責(zé)任鏈模式的定義:使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免請(qǐng)求的發(fā)送者和接受者之間的耦合關(guān)系, 將這個(gè)對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求,直到有一個(gè)對(duì)象處理他為止。這里就不再過(guò)多的介紹什么是責(zé)任鏈模式,主要來(lái)說(shuō)說(shuō)java中如何編寫(xiě)。主要從下面3個(gè)框架中的代碼中介紹。

  • servlet中的filter
  • dubbo中的filter
  • mybatis中的plugin 這3個(gè)框架在實(shí)現(xiàn)責(zé)任鏈方式不盡相同。

servlet中的Filter

servlet中分別定義了一個(gè) Filter和FilterChain的接口,核心代碼如下:

public final class ApplicationFilterChain implements FilterChain {
  private int pos = 0; //當(dāng)前執(zhí)行filter的offset
  private int n; //當(dāng)前filter的數(shù)量
  private ApplicationFilterConfig[] filters; //filter配置類(lèi),通過(guò)getFilter()方法獲取Filter
  private Servlet servlet
  @Override
  public void doFilter(ServletRequest request, ServletResponse response) {
    if (pos < n) {
      ApplicationFilterConfig filterConfig = filters[pos++];
      Filter filter = filterConfig.getFilter();
      filter.doFilter(request, response, this);
    } else {
      // filter都處理完畢后,執(zhí)行servlet
      servlet.service(request, response);
    }
  }
}

代碼還算簡(jiǎn)單,結(jié)構(gòu)也比較清晰,定義一個(gè)Chain,里面包含了Filter列表和servlet,達(dá)到在調(diào)用真正servlet之前進(jìn)行各種filter邏輯。

責(zé)任鏈模式如何在Java項(xiàng)目中實(shí)現(xiàn)

Dubbo中的Filter

Dubbo在創(chuàng)建Filter的時(shí)候是另外一個(gè)方法,通過(guò)把Filter封裝成 Invoker的匿名類(lèi),通過(guò)鏈表這樣的數(shù)據(jù)結(jié)構(gòu)來(lái)完成責(zé)任鏈,核心代碼如下:

private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
  Invoker<T> last = invoker;
  //只獲取滿(mǎn)足條件的Filter
  List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
  if (filters.size() > 0) {
    for (int i = filters.size() - 1; i >= 0; i --) {
      final Filter filter = filters.get(i);
      final Invoker<T> next = last;
      last = new Invoker<T>() {
        ...
        public Result invoke(Invocation invocation) throws RpcException {
          return filter.invoke(next, invocation);
        }
        ...
      };
    }
  }
  return last;
}

Dubbo的責(zé)任鏈就沒(méi)有類(lèi)似FilterChain這樣的類(lèi)吧Filter和調(diào)用Invoker結(jié)合起來(lái),而是通過(guò)創(chuàng)建一個(gè)鏈表,調(diào)用的時(shí)候我們只知道第一個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)包含了下一個(gè)調(diào)用的節(jié)點(diǎn)信息。 這里的雖然Invoker封裝Filter沒(méi)有顯示的指定next,但是通過(guò)java匿名類(lèi)和final的機(jī)制達(dá)到同樣的效果。

責(zé)任鏈模式如何在Java項(xiàng)目中實(shí)現(xiàn)

Mybatis中的Plugin

Mybatis可以配置各種Plugin,無(wú)論是官方提供的還是自己定義的,Plugin和Filter類(lèi)似,就在執(zhí)行Sql語(yǔ)句的時(shí)候做一些操作。Mybatis的責(zé)任鏈則是通過(guò)動(dòng)態(tài)代理的方式,使用Plugin代理實(shí)際的Executor類(lèi)。(這里實(shí)際還使用了組合模式,因?yàn)镻lugin可以嵌套代理),核心代碼如下:

public class Plugin implements InvocationHandler{
  private Object target;
  private Interceptor interceptor;
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {   
    if (滿(mǎn)足代理?xiàng)l件) {
      return interceptor.intercept(new Invocation(target, method, args));
    }
    return method.invoke(target, args);   
  }
  //對(duì)傳入的對(duì)象進(jìn)行代理,可能是實(shí)際的Executor類(lèi),也可能是Plugin代理類(lèi)
  public static Object wrap(Object target, Interceptor interceptor) {
    Class<&#63;> type = target.getClass();
    Class<&#63;>[] interfaces = getAllInterfaces(type, signatureMap);
    if (interfaces.length > 0) {
      return Proxy.newProxyInstance(
          type.getClassLoader(),
          interfaces,
          new Plugin(target, interceptor, signatureMap));
    }
    return target;
  }
}

 簡(jiǎn)單的示意圖如下:

責(zé)任鏈模式如何在Java項(xiàng)目中實(shí)現(xiàn)

上述就是小編為大家分享的責(zé)任鏈模式如何在Java項(xiàng)目中實(shí)現(xiàn)了,如果剛好有類(lèi)似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI