zoukankan      html  css  js  c++  java
  • dubbo @Activate 注解使用和实现解析

     Activate注解表示一个扩展是否被激活(使用),可以放在类定义和方法上

               dubbo用它在spi扩展类定义上,表示这个扩展实现激活条件和时机

    先看下定义:

     1 @Documented
     2 @Retention(RetentionPolicy.RUNTIME)
     3 @Target({ElementType.TYPE, ElementType.METHOD})
     4 public @interface Activate {
     5     /**
     6      * Group过滤条件。
     7      * <br />
     8      * 包含{@link ExtensionLoader#getActivateExtension}的group参数给的值,则返回扩展。
     9      * <br />
    10      * 如没有Group设置,则不过滤。
    11      */
    12     String[] group() default {};
    13 
    14     /**
    15      * Key过滤条件。包含{@link ExtensionLoader#getActivateExtension}的URL的参数Key中有,则返回扩展。
    16      * <p/>
    17      * 示例:<br/>
    18      * 注解的值 <code>@Activate("cache,validatioin")</code>,
    19      * 则{@link ExtensionLoader#getActivateExtension}的URL的参数有<code>cache</code>Key,或是<code>validatioin</code>则返回扩展。
    20      * <br/>
    21      * 如没有设置,则不过滤。
    22      */
    23     String[] value() default {};
    24 
    25     /**
    26      * 排序信息,可以不提供。
    27      */
    28     String[] before() default {};
    29 
    30     /**
    31      * 排序信息,可以不提供。
    32      */
    33     String[] after() default {};
    34 
    35     /**
    36      * 排序信息,可以不提供。
    37      */
    38     int order() default 0;
    39 }
    View Code

    它有两个设置过滤条件的字段,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,返回要激活使用的扩展。

      1 /**
      2  * Dubbo使用的扩展点获取。<p>
      3  * <ul>
      4  * <li>自动注入关联扩展点。</li>
      5  * <li>自动Wrap上扩展点的Wrap类。</li>
      6  * <li>缺省获得的的扩展点是一个Adaptive Instance。
      7  * </ul>
      8  */
      9 public class ExtensionLoader<T> 类中有如下四个方法
     10 
     11 /**
     12      * This is equivalent to <pre>
     13      *     getActivateExtension(url, key, null);
     14      * </pre>
     15      * 在所有的激活中,要使用key 指定的扩展
     16      * @param url url
     17      * @param key url parameter key which used to get extension point names
     18      * @return extension list which are activated.
     19      * @see #getActivateExtension(com.alibaba.dubbo.common.URL, String, String)
     20      */
     21     public List<T> getActivateExtension(URL url, String key)
     22 
     23       /**
     24      * This is equivalent to <pre>
     25      *     getActivateExtension(url, url.getParameter(key).split(","), null);
     26      * </pre>
     27      * 在所有的激活中,要指定的group 外加 使用key 指定的扩展
     28      * @param url   url
     29      * @param key   url parameter key which used to get extension point names
     30      * @param group group
     31      * @return extension list which are activated.
     32      * @see #getActivateExtension(com.alibaba.dubbo.common.URL, String[], String)
     33      */
     34     public List<T> getActivateExtension(URL url, String key, String group)
     35 
     36       /**
     37      * This is equivalent to <pre>
     38      *     getActivateExtension(url, values, null);
     39      * </pre>
     40      * 在所有的激活中 values指定的扩展
     41      * @param url    url
     42      * @param values extension point names
     43      * @return extension list which are activated
     44      * @see #getActivateExtension(com.alibaba.dubbo.common.URL, String[], String)
     45      */
     46     public List<T> getActivateExtension(URL url, String[] values)
     47 
     48     //最后其实都有下面方法实现
     49        /**
     50      * Get activate extensions.
     51      * 加载active扩展
     52      * @param url    url
     53      * @param values extension point names
     54      * @param group  group
     55      * @return extension list which are activated
     56      * @see com.alibaba.dubbo.common.extension.Activate
     57      */
     58     public List<T> getActivateExtension(URL url, String[] values, String group) {
     59         List<T> exts = new ArrayList<T>();
     60         List<String> names = values == null ? new ArrayList<String>(0) : Arrays.asList(values);
     61         if (!names.contains(Constants.REMOVE_VALUE_PREFIX + Constants.DEFAULT_KEY)) {
     62             getExtensionClasses();
     63             //cachedActivates里放的map结构 接口实现扩展名:其上的Activate对象
     64             for (Map.Entry<String, Activate> entry : cachedActivates.entrySet()) {//遍历所有Activate注解对象
     65                 String name = entry.getKey();//spi 扩展名
     66                 Activate activate = entry.getValue();
     67                 if (isMatchGroup(group, activate.group())) {//如果有group匹配
     68                     T ext = getExtension(name);//加在扩展类
     69                     //name不在 values 指定之列,并且没排除name,并且activate的value 在url有对应参数,就算激活
     70                     if (!names.contains(name)
     71                             && !names.contains(Constants.REMOVE_VALUE_PREFIX + name)
     72                             && isActive(activate, url)) {
     73                         //
     74                         exts.add(ext);
     75                     }
     76                 }
     77             }
     78             //排序Activate 具体实现在ActivateComparator里,实现了Comparator 接口compare方法
     79             Collections.sort(exts, ActivateComparator.COMPARATOR);
     80         }
     81         List<T> usrs = new ArrayList<T>();
     82         for (int i = 0; i < names.size(); i++) {
     83             String name = names.get(i);
     84             if (!name.startsWith(Constants.REMOVE_VALUE_PREFIX)
     85                     && !names.contains(Constants.REMOVE_VALUE_PREFIX + name)) {
     86                 //遍历所有没有排除的扩展名
     87                 if (Constants.DEFAULT_KEY.equals(name)) {
     88                     if (usrs.size() > 0) {
     89                         exts.addAll(0, usrs);
     90                         usrs.clear();
     91                     }
     92                 } else {
     93                     //通过扩展名,加载扩展添加到结果集
     94                     T ext = getExtension(name);
     95                     usrs.add(ext);
     96                 }
     97             }
     98         }
     99         if (usrs.size() > 0) {
    100             exts.addAll(usrs);
    101         }
    102     //返回符合条件的激活扩展
    103         return exts;
    104     }
    View Code
     
  • 相关阅读:
    如何做好不擅长的测试任务
    [ Python入门教程 ] Python中日志记录模块logging使用实例
    [ Python入门教程 ] Python中日期时间datetime模块使用实例
    cmd命令行窗口和文件目录资源管理器快速切换
    [ Python入门教程 ] Python中JSON模块基本使用方法
    [ PyQt入门教程 ] PyQt5中多线程模块QThread使用方法
    [ PyQt入门教程 ] PyQt5中数据表格控件QTableWidget使用方法
    设计模式目录
    我的软考架构师之路:目录(共22篇)
    算法篇:目录
  • 原文地址:https://www.cnblogs.com/xingzc/p/9134060.html
Copyright © 2011-2022 走看看