作者:周可强
一、责任链模式简介
1、责任链模式定义
责任链(Chain of Responsibility)模式的定义:为了防止申请发送者与多个申请解决者耦合在一起,于是将所有申请的解决者通过前一对象记住其下一个对象的援用而连成一条链;当有申请产生时,可将申请沿着这条链传递,直到有对象解决它为止。在责任链模式中,客户只须要将申请发送到责任链上即可,毋庸关怀申请的解决细节和申请的传递过程,申请会主动进行传递。所以责任链将申请的发送者和申请的解决者解耦了。
2、责任链特点
责任链模式是一种对象行为型模式,
其次要长处如下。
1).升高了对象之间的耦合度。该模式使得一个对象毋庸晓得到底是哪一个对象解决其申请以及链的构造,发送者和接收者也毋庸领有对方的明确信息。
2).加强了零碎的可扩展性。能够依据须要减少新的申请解决类,满足开闭准则。
3).加强了给对象指派职责的灵活性。当工作流程发生变化,能够动静地扭转链内的成员或者调动它们的秩序,也可动静地新增或者删除责任。责任链简化了对象之间的连贯。每个对象只需放弃一个指向其后继者的援用,不需放弃其余所有解决者的援用,这防止了应用泛滥的 if 或者 if···else 语句。
4).责任分担。每个类只须要解决本人该解决的工作,不该解决的传递给下一个对象实现,明确各类的责任范畴,合乎类的繁多职责准则。
其次要毛病如下。
1).不能保障每个申请肯定被解决。因为一个申请没有明确的接收者,所以不能保障它肯定会被解决,该申请可能始终传到链的末端都得不到解决。
2).对比拟长的职责链,申请的解决可能波及多个解决对象,零碎性能将受到肯定影响。
3).职责链建设的合理性要靠客户端来保障,减少了客户端的复杂性,可能会因为职责链的谬误设置而导致系统出错,如可能会造成循环调用。
3、责任链结构图
二、Dubbo中的责任链模式
1、过滤器日志
通过打印过滤器的日志,咱们能够看到在公布服务的过程中,会顺次通过dubbo的每个过滤器类,以此来保障服务的欠缺。
2、过滤器简图
dubbo通过将每个过滤器类filter封装成dubbo的外围模型invoker进行组装,最终造成早晨的过滤器责任链filterChain。
3、过滤器类图
Protocol是外围模型invoker裸露和援用的主性能入口,采纳SPI的接口,他的两个办法export和refer别离对应provider和consumer端的服务性能,ProtocolFilterWapper则是Dubbo的过滤器的次要实现类,通过重写的export和refer指向buildInvokerChain办法,在buildInvokerChain中进行责任链的获取与组装,在extensionLoader中通过SPI获取Filter的各实现类,并通过ActivateComparator进行排序,最终造成残缺的责任链。
三、Dubbo中各Filter责任介绍
1、provider用到的filter
2、consumer用到的filter
四、源码探析
进入到外围类ProtocolFilterWrapper中,在实现类中export和refer,都采纳雷同的结构责任链办法buildInvokerChain,只是通过参数group进行辨别
在buildInvokerChain中,通过getActivateExtension获取过滤器数组,并在之后封装成外围模型invoker并组装成责任链
private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) { Invoker<T> last = invoker; // 取得过滤器数组 (曾经排好序的) List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group); // 创立带 Filter 链的 Invoker 对象 if (!filters.isEmpty()) { for (int i = filters.size() - 1; i >= 0; i--) { 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); } @Override public void destroy() { invoker.destroy(); } @Override public String toString() { return invoker.toString(); } }; } } System.out.println("group:" + group); for (Filter filter : filters) { System.out.println(filter.getClass()); } return last; }
getActivateExtension是次要的组装逻辑,他蕴含获取与排序等逻辑
首先进行判断是否采纳零碎默认的Filter过滤器,并对每一个零碎过滤器进行校验是否移除,而后对系统过滤器排序,再通过指定的参数,减少用户自定义的过滤器组装责任链
public List<T> getActivateExtension(URL url, String key, String group) { // 从 Dubbo URL 取得参数值 String value = url.getParameter(key); // 取得合乎主动激活条件的拓展对象数组 return getActivateExtension(url, value == null || value.length() == 0 ? null : Constants.COMMA_SPLIT_PATTERN.split(value), group); }public List<T> getActivateExtension(URL url, String[] values, String group) { List<T> exts = new ArrayList<T>(); //所有用户本人配置的filter信息(有些Filter是默认激活的,有些是配置激活的,这里的names就指的配置激活的filter信息) List<String> names = values == null ? new ArrayList<String>(0) : Arrays.asList(values); // 解决主动激活的拓展对象们 // 判断不存在配置 `"-name"` 。例如,<dubbo:service filter="-default" /> ,代表移除所有默认过滤器。 if (!names.contains(Constants.REMOVE_VALUE_PREFIX + Constants.DEFAULT_KEY)) { // 取得拓展实现类数组 getExtensionClasses(); // 循环 for (Map.Entry<String, Activate> entry : cachedActivates.entrySet()) { //name指的是SPI读取的配置文件的key String name = entry.getKey(); Activate activate = entry.getValue(); if (isMatchGroup(group, activate.group())) { // 匹配分组 // 取得拓展对象 T ext = getExtension(name); if (!names.contains(name) // 不蕴含在自定义配置里。如果蕴含,会在上面的代码解决。 && !names.contains(Constants.REMOVE_VALUE_PREFIX + name) // 判断是否配置移除。例如 <dubbo:service filter="-monitor" />,则 MonitorFilter 会被移除 && isActive(activate, url)) { // 判断是否激活 exts.add(ext); } } } // 排序 Collections.sort(exts, ActivateComparator.COMPARATOR); } // 解决自定义配置的拓展对象们。例如在 <dubbo:service filter="demo" /> ,代表须要退出 DemoFilter List<T> usrs = new ArrayList<T>(); for (int i = 0; i < names.size(); i++) { String name = names.get(i); if (!name.startsWith(Constants.REMOVE_VALUE_PREFIX) && !names.contains(Constants.REMOVE_VALUE_PREFIX + name)) { // 判断非移除的 // 将配置的自定义在主动激活的拓展对象们后面。例如,<dubbo:service filter="demo,default,demo2" /> ,则 DemoFilter 就会放在默认的过滤器后面。 if (Constants.DEFAULT_KEY.equals(name)) { if (!usrs.isEmpty()) { exts.addAll(0, usrs); usrs.clear(); } } else { // 取得拓展对象 T ext = getExtension(name); usrs.add(ext); } } } // 增加到后果集 if (!usrs.isEmpty()) { exts.addAll(usrs); } return exts; }
零碎默认的过滤器和udf过滤器进行辨别
以ContextFilter为例,零碎默认过滤器蕴含Activate注解,用于指定所属分组与排序权重,用户本人实现的过滤器则不能增加Activate注解通过公布时指定所需的过滤器
咱们看下具体的排序比拟办法,首先判断Activate注解是否指定before和after参数用来指定排序,若不存在则采纳order权重进行排序
ActivateComparator.classpublic int compare(Object o1, Object o2) { // 根本排序 if (o1 == null && o2 == null) { return 0; } if (o1 == null) { return -1; } if (o2 == null) { return 1; } if (o1.equals(o2)) { return 0; } Activate a1 = o1.getClass().getAnnotation(Activate.class); Activate a2 = o2.getClass().getAnnotation(Activate.class); // 应用注解的 `after` 和 `before` 属性,排序 if ((a1.before().length > 0 || a1.after().length > 0 || a2.before().length > 0 || a2.after().length > 0) // (a1 或 a2) 存在 (`after` 或 `before`) 属性。 && o1.getClass().getInterfaces().length > 0 && o1.getClass().getInterfaces()[0].isAnnotationPresent(SPI.class)) { // 实现的接口,有 @SPI 注解。 // 取得拓展加载器 ExtensionLoader<?> extensionLoader = ExtensionLoader.getExtensionLoader(o1.getClass().getInterfaces()[0]); // 以 a1 的视角,进行一次比拟 if (a1.before().length > 0 || a1.after().length > 0) { String n2 = extensionLoader.getExtensionName(o2.getClass()); for (String before : a1.before()) { if (before.equals(n2)) { return -1; } } for (String after : a1.after()) { if (after.equals(n2)) { return 1; } } } // 以 a2 的视角,进行一次比拟。 if (a2.before().length > 0 || a2.after().length > 0) { String n1 = extensionLoader.getExtensionName(o1.getClass()); for (String before : a2.before()) { if (before.equals(n1)) { return 1; } } for (String after : a2.after()) { if (after.equals(n1)) { return -1; } } } } // 应用注解的 `order` 属性,排序。 int n1 = a1 == null ? 0 : a1.order(); int n2 = a2 == null ? 0 : a2.order(); // never return 0 even if n1 equals n2, otherwise, o1 and o2 will override each other in collection like HashSet return n1 > n2 ? 1 : -1; }
总结:
责任链模式是设计模式中简略且常见的设计模式,可能咱们日常中也会常常利用责任链模式,dubbo中的责任链模式将灵活性施展的很充沛,不论是从分组概念、通过注解指定排序的优先级、每个filter的是否移除 等,将每个filter做成了可插拔的,缩小对代码的侵入性,这点是十分值得咱们学习的。