<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          從Servlet、Dubbo、Mybatis聊聊責(zé)任鏈究竟怎么用

          共 2478字,需瀏覽 5分鐘

           ·

          2021-01-06 14:24

          作者:atheva?

          來源:https://dwz.cn/1TtgW7Ud

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

          • servlet中的filter

          • dubbo中的filter

          • mybatis中的plugin

          servlet中的Filter

          servlet中分別定義了一個 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配置類,通過getFilter()方法獲取Filter
          ????private?Servlet?servlet

          ????@Override
          ????public?void?doFilter(ServletRequest?request,?ServletResponse?response)?{
          ????????if?(pos?????????????ApplicationFilterConfig?filterConfig?=?filters[pos++];
          ????????????Filter?filter?=?filterConfig.getFilter();
          ????????????filter.doFilter(request,?response,?this);
          ????????}?else?{
          ????????????//?filter都處理完畢后,執(zhí)行servlet
          ????????????servlet.service(request,?response);
          ????????}
          ????}

          }

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


          Dubbo中的Filter

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

          private?static??Invoker?buildInvokerChain(final?Invoker?invoker,?String?key,?String?group)?{
          ????Invoker?last?=?invoker;
          ????//只獲取滿足條件的Filter
          ????List?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?next?=?last;
          ????????????last?=?new?Invoker()?{
          ????????????????...
          ????????????????public?Result?invoke(Invocation?invocation)?throws?RpcException?{
          ????????????????????return?filter.invoke(next,?invocation);
          ????????????????}
          ????????????????...
          ????????????};
          ????????}
          ????}
          ????return?last;
          }

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


          Mybatis中的Plugin

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

          public?class?Plugin?implements?InvocationHandler{
          ????private?Object?target;
          ????private?Interceptor?interceptor;
          ????@Override
          ????public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)?throws?Throwable?{??????
          ????????if?(滿足代理條件)?{
          ????????????return?interceptor.intercept(new?Invocation(target,?method,?args));
          ????????}
          ????????return?method.invoke(target,?args);?????
          ????}

          ????//對傳入的對象進(jìn)行代理,可能是實(shí)際的Executor類,也可能是Plugin代理類
          ????public?static?Object?wrap(Object?target,?Interceptor?interceptor)?{

          ????????Class?type?=?target.getClass();
          ????????Class[]?interfaces?=?getAllInterfaces(type,?signatureMap);
          ????????if?(interfaces.length?>?0)?{
          ????????????return?Proxy.newProxyInstance(
          ????????????????????type.getClassLoader(),
          ????????????????????interfaces,
          ????????????????????new?Plugin(target,?interceptor,?signatureMap));
          ????????}
          ????????return?target;
          ????}
          }?

          簡單的示意圖如下:


          總結(jié)

          這里簡單介紹了Servlet、Dubbo、Mybatis對責(zé)任鏈模式的不同實(shí)現(xiàn)手段,其中Servlet是相對比較清晰,又易于實(shí)現(xiàn)的方式,而Dubbo和Mybatis則適合在原有代碼基礎(chǔ)上,增加責(zé)任鏈模式代碼改動量最小的。


          瀏覽 19
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天拍,天天射,天天撸 | 国产激情无码视频 | 一级黄色视频直播 | 最新中文字幕2019视频在线不卡 | www.插|