dubbo @Activate 註解使用和實現解析

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;
    }
相關文章
相關標籤/搜索