zoukankan      html  css  js  c++  java
  • dubbo ActivateExtension

    对于集合类扩展点,比如:Filter, InvokerListener, ExportListener, TelnetHandler, StatusChecker等, 可以同时加载多个实现,此时,可以用自动激活来简化配置。

    public List<T> getActivateExtension(URL url, String key) {
        return getActivateExtension(url, key, null);
    }
    // 存Activate修饰的注解集合
    private final Map<String, Activate> cachedActivates = new ConcurrentHashMap<String, Activate>();

    组装出可用的ActivateExtension

    public List<T> getActivateExtension(URL url, String[] values, String group) {
        List<T> exts = new ArrayList<T>();
        List<String> names = values == null ? new ArrayList<String>(0) : Arrays.asList(values);
        if (! names.contains(Constants.REMOVE_VALUE_PREFIX + Constants.DEFAULT_KEY)) {
            getExtensionClasses();
            for (Map.Entry<String, Activate> entry : cachedActivates.entrySet()) {
                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) 
                            && isActive(activate, url)) {
                        exts.add(ext);
                    }
                }
            }
            Collections.sort(exts, ActivateComparator.COMPARATOR);
        }
        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)) {
               if (Constants.DEFAULT_KEY.equals(name)) {
                  if (usrs.size() > 0) {
                  exts.addAll(0, usrs);
                  usrs.clear();
                  }
               } else {
               T ext = getExtension(name);
               usrs.add(ext);
               }
            }
        }
        if (usrs.size() > 0) {
           exts.addAll(usrs);
        }
        return exts;
    }

    实际和AdaptiveExtension一样在解析是,如果被注解了Activate就会放到cachedActivates里。

    以dubbo中的filter为例子,ProtocolFilterWrapper中的代码,调用getActivateExtension方法获得激活的filters,然后以此执行,所谓的集合类的扩展点启示dubbo滋生代码已经决定了的,调用形式不同而已:

    private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
        Invoker<T> last = invoker;
        // 获取配置的filters
        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;
    }

    在看调用这个方法的代码:

    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
            return protocol.export(invoker);
        }
        // Constants.SERVICE_FILTER_KEY = "service.filter"
        return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
    }
    
    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);
    }
    看到key是service.filter,那对应到dubbo的使用文档上看其实就是的filter参数,就可以对应到URL参数中的service.filter。也可以通过编码方式:ProviderConfig的setFilter方法 进行手动配置。
  • 相关阅读:
    J2EE系列 (一) 几个技术规范
    MyEclipse 10 优化技巧
    J2EE (二) Servlet设置Session Cookies
    CSS 外层box自动计算高度的问题
    UI设计技巧Div封闭式Div导致页面显示异常
    Windows 7 IIS7 无法启动, 显示WAS & W3SVC没有启动的错误提示
    Windows 7 截图
    GridView技巧增加序号列
    ERWin & ERStudio图里的实线和虚线的含义
    [转]CSS布局口诀 CSS BUG顺口溜
  • 原文地址:https://www.cnblogs.com/killbug/p/7235262.html
Copyright © 2011-2022 走看看