美文网首页
开源框架中的职责链分析

开源框架中的职责链分析

作者: 晴天哥_王志 | 来源:发表于2022-08-13 13:17 被阅读0次

    Tomcat

    Tomcat 职责链
    • Tomcat 的职责链以数组的形式进行维护,通过职责链的总长度 n 和执行位置 pos进行维护。
    • Tomcat 的职责链的执行过程借助于每个 Filter 本身

    职责链的构建

    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;
    
        }
    }
    
    • 职责链通过ApplicationFilterConfig[] filters维护所有的 Filter 对象。
    • 职责链添加 Filter 通过addFilter实现,本质上是往数组filters添加元素并更改总数 n 。

    职责链的执行

    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);
            } 
        }
    
    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 {
            // 执行职责链当中的下一个 Filter 对象,等价于执行 FilterChain 的internalDoFilter方法
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }
    
    • FilterChain 的执行逻辑在internalDoFilter中,核心就是从职责链的数组filters当中获取当前待执行Filter 比国内调用doFilter逻辑。
    • 每个 Filter 内部如TimeFilter为例,优先执行本 Filter 的业务逻辑,然后通过filterChain.doFilter驱动职责链上的下一个 Filter 执行。

    Mybatis

    Mybatis职责链
    • Mybatis 的职责链以 链表的形式进行维护,职责链元素是拦截器 Interceptor 对象proxy 封装。
    • Mybatis 的职责链的执行过程借助于每个Proxy本身的自驱。

    职责链的构建

    public class InterceptorChain {
    
      private final List<Interceptor> interceptors = new ArrayList<>();
    
      // 进行拦截器的织入
      public Object pluginAll(Object target) {
        for (Interceptor interceptor : interceptors) {
          target = interceptor.plugin(target);
        }
        return target;
      }
    }
    
    ---------------------------
    
    public interface Interceptor {
    
      Object intercept(Invocation invocation) throws Throwable;
    
      default Object plugin(Object target) {
        return Plugin.wrap(target, this);
      }
    
      default void setProperties(Properties properties) {
      }
    }
    
    -------------------------
    
    public class Plugin implements InvocationHandler {
    
      private final Object target;
      private final Interceptor interceptor;
      private final Map<Class<?>, Set<Method>> signatureMap;
    
      private Plugin(Object target, Interceptor interceptor, Map<Class<?>, Set<Method>> signatureMap) {
        this.target = target;
        this.interceptor = interceptor;
        this.signatureMap = signatureMap;
      }
    
      public static Object wrap(Object target, Interceptor interceptor) {
        Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(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;
      }
    
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
          Set<Method> methods = signatureMap.get(method.getDeclaringClass());
          if (methods != null && methods.contains(method)) {
            return interceptor.intercept(new Invocation(target, method, args));
          }
          return method.invoke(target, args);
        } catch (Exception e) {
        }
      }
    }
    
    • InterceptorChain负责遍历所有的拦截器 Interceptor 对象构建职责链。
    • 在 Plugin#wrap方法中将 target 和 Interceptor 对象封装成Plugin对象然后以 动态代理Proxy 的形式返回。
    • 每个Proxy 对象会成为下一个 Interceptor 的内部的 target 对象,形式链式关系。

    职责链的执行

    public class Plugin implements InvocationHandler {
    
      private final Object target;
      private final Interceptor interceptor;
      private final Map<Class<?>, Set<Method>> signatureMap;
    
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
          Set<Method> methods = signatureMap.get(method.getDeclaringClass());
          if (methods != null && methods.contains(method)) {
            // 执行拦截器的逻辑
            return interceptor.intercept(new Invocation(target, method, args));
          }
          return method.invoke(target, args);
        } catch (Exception e) {
        }
      }
    }
    
    -----------------------
    
    @Intercepts({ @Signature(type = Executor.class, method = "update"
            , args = { MappedStatement.class, Object.class}) })
    public class SelfDefinePlugin implements Interceptor {
    
        public Object intercept(Invocation invocation) throws Throwable {
            
            // 执行拦截器相关的逻辑
    
            // 执行下一个拦截器
            return invocation.proceed();
        }
    
        public Object plugin(Object target) {
            return Plugin.wrap(target,this);
        }
    
        public void setProperties(Properties properties) {
    
        }
    }
    
    -----------------------
    
    public class Invocation {
    
      private final Object target;
      private final Method method;
      private final Object[] args;
    
      public Invocation(Object target, Method method, Object[] args) {
        this.target = target;
        this.method = method;
        this.args = args;
      }
    
      public Object proceed() throws InvocationTargetException, IllegalAccessException {
        return method.invoke(target, args);
      }
    }
    
    • Proxy对象执行plugin的invoke方法,在invoke方法内部会访问拦截器 interceptor 对象的intercept方法。
    • interceptor对象实现了Interceptor接口并重写了intercept方法,改写的intercept内部优先执行拦截器本身的逻辑,再通过invocation.proceed触发职责链上下一个拦截器对象的执行。
    • Invocation对象封装下一个拦截器对象的 Proxy 对象即 target 对象,执行方法即method对象。

    Dubbo

    Dubbo 职责链
    • Dubbo 的职责链以 链表的形式进行维护,职责链元素是ProtocolFilterWrapper的匿名类,匿名类对象包含了下一个职责链元素。
    • Dubbo 的职责链的执行过程借助于每个ProtocolFilterWrapper匿名类对象的自驱。

    职责链的构建

    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 Class<T> getInterface() {
                            return invoker.getInterface();
                        }
    
                        @Override
                        public URL getUrl() {
                            return invoker.getUrl();
                        }
    
                        @Override
                        public boolean isAvailable() {
                            return invoker.isAvailable();
                        }
    
                        @Override
                        public Result invoke(Invocation invocation) throws RpcException {
                            return filter.invoke(next, invocation);
                        }
                    };
                }
            }
            return last;
        }
    }
    
    • Dubbo的职责链通过遍历所有的filters并依次创建ProtocolFilterWrapper的匿名类对象进行链式串联。
    • new Invoker<T>()的操作会生成ProtocolFilterWrapper匿名类对象。
    static final class ProtocolFilterWrapper.1 implements Invoker < T > {
        final Invoker val$invoker;
        final Filter val$filter;
        final Invoker val$next;
    
     ProtocolFilterWrapper.1(Invoker invoker, Filter filter, Invoker invoker2) {
         this.val$invoker = invoker;
         this.val$filter = filter;
         this.val$next = invoker2;
     }
    }
    
    • ProtocolFilterWrapper.1作为内部匿名类包含了 filter 对象和下一个职责链元素 invoker2.

    职责链的构建

    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;
        }
    }
    
    --------------------------
    
    @Activate(group = {Constants.CONSUMER, Constants.PROVIDER}, value = Constants.CACHE_KEY)
    public class CacheFilter implements Filter {
    
        private CacheFactory cacheFactory;
    
        public void setCacheFactory(CacheFactory cacheFactory) {
            this.cacheFactory = cacheFactory;
        }
    
        @Override
        public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
            if (cacheFactory != null && ConfigUtils.isNotEmpty(invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.CACHE_KEY))) {
                Cache cache = cacheFactory.getCache(invoker.getUrl(), invocation);
                if (cache != null) {
                    String key = StringUtils.toArgumentString(invocation.getArguments());
                    Object value = cache.get(key);
                    if (value != null) {
                        return new RpcResult(value);
                    }
    
                    // 执行下一个 Filter 的调用
                    Result result = invoker.invoke(invocation);
    
                    if (!result.hasException() && result.getValue() != null) {
                        cache.put(key, result.getValue());
                    }
                    return result;
                }
            }
            return invoker.invoke(invocation);
        }
    }
    
    • 职责链的执行参考ProtocolFilterWrapper.1#invoke方法,调用当前 Filter 对象的 invoke 方法(this.val$filter.invoke)。
    • 每个具体的 Filter 如CacheFilter会执行自生的逻辑,然后调用下一个 Filter 对象的 invoke 方法来驱动职责链的执行。

    相关文章

      网友评论

          本文标题:开源框架中的职责链分析

          本文链接:https://www.haomeiwen.com/subject/bicqgrtx.html