表示一个扩展是否被激活(使用),可以放在类定义和方法上,
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 }