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 }
它有兩個設置過濾條件的字段,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 }