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

复制代码

 

出处:https://www.cnblogs.com/wangzhuxing/p/9826555.html
posted @ 2021-03-07 11:05  十点书屋  阅读(665)  评论(0)    收藏  举报