一. Filter原理 最近刚刚接触dubbo,瞬间被dubbo的简洁和扩展性圈粉了,用郭大爷的话来说就是又勾勾又丢丢,一想之美。代码算上测试一共短短12W行,没有像spring那么复杂的继承结构,但是对各种设计模式和架构设计理念的运用又极度的优雅。
跑题了,这里主要记录一下Filter的作用原理。Filter在很多地方都有用到,比如Servlet。Dubbo中也不例外,在一个Invoker被调用之前,可以配置多个Filter去过滤一次调用。Filter的作用可以看做一个AOP,在真正调用的前后做一些工作,并且Filter可以非常方便的层层嵌套。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 public <T> Invoker<T> refer (Class<T> type, URL url) throws RpcException { if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) { return protocol.refer(type, url); } return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER); } 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); 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 Class<T> getInterface () { return invoker.getInterface(); } public URL getUrl () { return invoker.getUrl(); } public boolean isAvailable () { return invoker.isAvailable(); } public Result invoke (Invocation invocation) throws RpcException { return filter.invoke(next, invocation); } public void destroy () { invoker.destroy(); } @Override public String toString () { return invoker.toString(); } }; } } return last; }
这段代码可以非常清晰的看到filter是如何被一层一层组装的。
二. 自己模拟实现
目录结构如上,Filter和Invoker也超级简单:
1 2 3 4 5 6 7 public interface Filter { int invoke (Invoker invoker, int i) ; } public interface Invoker { int result (int i) ; }
看看实现类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 public class InvokerImpl implements Invoker { @Override public int result (int i) { System.out.println("invoker impl" ); return i * 2 ; } } public class FilterA implements Filter { @Override public int invoke (Invoker invoker, int i) { try { System.out.println("Filter A" ); int result = invoker.result(i); System.out.println("after Filter A" ); return result; }catch (Exception e) { throw e; } } } public class FilterB implements Filter { @Override public int invoke (Invoker invoker, int i) { try { System.out.println("Filter B" ); int result = invoker.result(i); System.out.println("after Filter B" ); return result; } catch (Exception e) { throw e; } } }
组装filter并测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Test { public static void main (String[] args) { Filter filter1 = new FilterA(); Filter filter2 = new FilterB(); List<Filter> filters = new ArrayList<>(); filters.addAll(Arrays.asList(filter1, filter2)); Invoker last = new InvokerImpl(); for (Filter filter : filters) { final Invoker next = last; last = (i) -> filter.invoke(next, i); } System.out.println(last.result(1 )); } }
这里要注意组装的顺序,决定最后先调用那个filter。
看看最后的运行结果:
1 2 3 4 5 6 Filter B Filter A invoker impl after Filter A after Filter B 2
结合以上代码,不难看出filter的执行顺序,filter其实就是一个硬编码的栈,用户可以决定在栈的什么地方做一个操作。