• dubbo系列七、dubbo @Activate 注解使用和实现解析


    一、用法

    Activate注解表示一个扩展是否被激活(使用),可以放在类定义和方法上,dubbo用它在spi扩展类定义上,表示这个扩展实现激活条件和时机。

    复制代码
    @Activate(group = Constants.PROVIDER)
    public class DrpcServerInterceptor implements Filter{
        
        private final ServerRequestInterceptor serverRequestInterceptor;
        private final ServerResponseInterceptor serverResponseInterceptor;
        
        public DrpcServerInterceptor() { 
            String sendUrl = ZipkinConfig.getProperty(ZipkinConstants.SEND_ADDRESS);
            Sender sender = OkHttpSender.create(sendUrl);
            Reporter<zipkin.Span> reporter = AsyncReporter.builder(sender).build();
            String application = ZipkinConfig.getProperty(ZipkinConstants.BRAVE_NAME);//RpcContext.getContext().getUrl().getParameter("application");
            Brave brave = new Brave.Builder(application).reporter(reporter).build();
            this.serverRequestInterceptor = brave.serverRequestInterceptor();
            this.serverResponseInterceptor = brave.serverResponseInterceptor();
        }
    。。。。
    }
    复制代码

    表示该类只在生产者生效。

    二、源码解析

    先看下接口定义:

    复制代码
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE, ElementType.METHOD})
    public @interface Activate {
        /**
         * Group过滤条件。
         * <br />
         * 包含{@link ExtensionLoader#getActivateExtension}的group参数给的值,则返回扩展。
         * <br />
         * 如没有Group设置,则不过滤。
         */
        String[] group() default {};
    
        /**
         * Key过滤条件。包含{@link ExtensionLoader#getActivateExtension}的URL的参数Key中有,则返回扩展。
         * <p/>
         * 示例:<br/>
         * 注解的值 <code>@Activate("cache,validatioin")</code>,
         * 则{@link ExtensionLoader#getActivateExtension}的URL的参数有<code>cache</code>Key,或是<code>validatioin</code>则返回扩展。
         * <br/>
         * 如没有设置,则不过滤。
         */
        String[] value() default {};
    
        /**
         * 排序信息,可以不提供。
         */
        String[] before() default {};
    
        /**
         * 排序信息,可以不提供。
         */
        String[] after() default {};
    
        /**
         * 排序信息,可以不提供。
         */
        int order() default 0;
    }
    复制代码

    它有两个设置过滤条件的字段,group,value 都是字符数组。用来指定这个扩展类在什么条件下激活。

    下面以com.alibaba.dubbo.rpc.filter接口的几个扩展来说明。

    //如MonitorFilter
    @Activate(group = {Constants.PROVIDER, Constants.CONSUMER})
    public class MonitorFilter implements Filter {
    
    }

    表示如果过滤器使用方(通过group指定)属于Constants.PROVIDER(服务提供方)或者Constants.CONSUMER(服务消费方)就激活使用这个过滤器。

    //再看这个扩展
    @Activate(group = Constants.PROVIDER, value = Constants.TOKEN_KEY)
    public class TokenFilter implements Filter {
    }

    表示如果过滤器使用方(通过group指定)属于Constants.PROVIDER(服务提供方)并且 URL中有参数 Constants.TOKEN_KEY(token)时就激活使用这个过滤器。

    再看下具体实现:

    dubbo在ExtensionLoader类,解析某个接口扩展实现类时,会把所有实现类中有Activate注解的,都先放到一个全局map中。

    Activate activate = clazz.getAnnotation(Activate.class);
    if (activate != null) {
        //如果有,加入,cachedActivates map 扩展名:实现类class,形式
        cachedActivates.put(names[0], activate);
    }

    然后提供了4个方法来具体使用cachedActivates,返回要激活使用的扩展。

    复制代码
     /**
         * This is equivalent to <pre>
         *     getActivateExtension(url, key, null);
         * </pre>
         * 在所有的激活中,要使用key 指定的扩展
         * @param url url
         * @param key url parameter key which used to get extension point names
         * @return extension list which are activated.
         * @see #getActivateExtension(com.alibaba.dubbo.common.URL, String, String)
         */
        public List<T> getActivateExtension(URL url, String key)
    
          /**
         * This is equivalent to <pre>
         *     getActivateExtension(url, url.getParameter(key).split(","), null);
         * </pre>
         * 在所有的激活中,要指定的group 外加 使用key 指定的扩展
         * @param url   url
         * @param key   url parameter key which used to get extension point names
         * @param group group
         * @return extension list which are activated.
         * @see #getActivateExtension(com.alibaba.dubbo.common.URL, String[], String)
         */
        public List<T> getActivateExtension(URL url, String key, String group)
    
          /**
         * This is equivalent to <pre>
         *     getActivateExtension(url, values, null);
         * </pre>
         * 在所有的激活中 values指定的扩展
         * @param url    url
         * @param values extension point names
         * @return extension list which are activated
         * @see #getActivateExtension(com.alibaba.dubbo.common.URL, String[], String)
         */
        public List<T> getActivateExtension(URL url, String[] values)
    
        //最后其实都有下面方法实现
           /**
         * Get activate extensions.
         * 加载active扩展
         * @param url    url
         * @param values extension point names
         * @param group  group
         * @return extension list which are activated
         * @see com.alibaba.dubbo.common.extension.Activate
         */
        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();
                //cachedActivates里放的map结构 接口实现扩展名:其上的Activate对象
                for (Map.Entry<String, Activate> entry : cachedActivates.entrySet()) {//遍历所有Activate注解对象
                    String name = entry.getKey();//spi 扩展名
                    Activate activate = entry.getValue();
                    if (isMatchGroup(group, activate.group())) {//如果有group匹配
                        T ext = getExtension(name);//加在扩展类
                        //name不在 values 指定之列,并且没排除name,并且activate的value 在url有对应参数,就算激活
                        if (!names.contains(name)
                                && !names.contains(Constants.REMOVE_VALUE_PREFIX + name)
                                && isActive(activate, url)) {
                            //
                            exts.add(ext);
                        }
                    }
                }
                //排序Activate 具体实现在ActivateComparator里,实现了Comparator 接口compare方法
                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;
        }
    复制代码
  • 相关阅读:
    【小白建站笔记】从购买域名及服务器到备案成功:以阿里云为例
    jarvisoj-Evil Exe
    jarvisoj-软件密码破解-2(CFF_100_1)
    Jarvis OJ-superexpress
    JarvisOJ-[xman2019]xfz
    csictf-Esrever
    分解质因数
    矩阵乘法
    python获取一组数个位数之和
    python计算字母出现次数
  • 原文地址:https://www.cnblogs.com/ceshi2016/p/12016425.html
Copyright © 2020-2023  润新知