Activate註解表示一個擴展是否被激活(使用),能夠放在類定義和方法上,dubbo用它在spi擴展類定義上,表示這個擴展實現激活條件和時機。先看下定義:java
@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接口的幾個擴展來講明。ui
//如MonitorFilter @Activate(group = {Constants.PROVIDER, Constants.CONSUMER}) public class MonitorFilter implements Filter { }
表示若是過濾器使用方(經過group指定)屬於Constants.PROVIDER(服務提供方)或者Constants.CONSUMER(服務消費方)就激活使用這個過濾器。url
//再看這個擴展 @Activate(group = Constants.PROVIDER, value = Constants.TOKEN_KEY) public class TokenFilter implements Filter { }
表示若是過濾器使用方(經過group指定)屬於Constants.PROVIDER(服務提供方)而且 URL中有參數 Constants.TOKEN_KEY(token)時就激活使用這個過濾器。spa
再看下具體實現:code
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; }