dubbo系列七、dubbo @Activate 注解使用和實現解析


一、用法

Activate注解表示一個擴展是否被激活(使用),可以放在類定義和方法上,dubbo用它在spi擴展類定義上,表示這個擴展實現激活條件和時機。

@Activate(group = Constants.PROVIDER)
public class DrpcServerInterceptor implements Filter{
    
    private final ServerRequestInterceptor serverRequestInterceptor;
    private final ServerResponseInterceptor serverResponseInterceptor;
    
    public DrpcServerInterceptor() { 
        String sendUrl = ZipkinConfig.getProperty(ZipkinConstants.SEND_ADDRESS);
        Sender sender = OkHttpSender.create(sendUrl);
        Reporter<zipkin.Span> reporter = AsyncReporter.builder(sender).build();
        String application = ZipkinConfig.getProperty(ZipkinConstants.BRAVE_NAME);//RpcContext.getContext().getUrl().getParameter("application");
        Brave brave = new Brave.Builder(application).reporter(reporter).build();
        this.serverRequestInterceptor = brave.serverRequestInterceptor();
        this.serverResponseInterceptor = brave.serverResponseInterceptor();
    }
。。。。
}

表示該類只在生產者生效。

二、源碼解析

先看下接口定義:

@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接口的幾個擴展來說明。

//如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,返回要激活使用的擴展。

 /**
     * 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;
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM