一、用法

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

dubbo系列七、dubbo @Activate 注解使用和实现解析的更多相关文章

  1. dubbo @Activate 注解使用和实现解析

    Activate注解表示一个扩展是否被激活(使用),可以放在类定义和方法上, dubbo用它在spi扩展类定义上,表示这个扩展实现激活条件和时机. 先看下定义: @Documented @Retent ...

  2. Spring框架系列(七)--Spring常用注解

    Spring部分: 1.声明bean的注解: @Component:组件,没有明确的角色 @Service:在业务逻辑层使用(service层) @Repository:在数据访问层使用(dao层) ...

  3. Spring系列之手写注解与配置文件的解析

    目录 Spring系列之IOC的原理及手动实现 Spring系列之DI的原理及手动实现 Spring系列之AOP的原理及手动实现 引入 在前面我们已经完成了IOC,DI,AOP的实现,基本的功能都已经 ...

  4. java基础解析系列(七)---ThreadLocal原理分析

    java基础解析系列(七)---ThreadLocal原理分析 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)-- ...

  5. Dubbo系列之 (七)链路层那些事(1)

    辅助链接 Dubbo系列之 (一)SPI扩展 Dubbo系列之 (二)Registry注册中心-注册(1) Dubbo系列之 (三)Registry注册中心-注册(2) Dubbo系列之 (四)服务订 ...

  6. Dubbo系列之 (七)网络层那些事(2)

    辅助链接 Dubbo系列之 (一)SPI扩展 Dubbo系列之 (二)Registry注册中心-注册(1) Dubbo系列之 (三)Registry注册中心-注册(2) Dubbo系列之 (四)服务订 ...

  7. Dubbo 系列(07-5)集群容错 - Mock

    Dubbo 系列(07-5)集群容错 - Mock [toc] Spring Cloud Alibaba 系列目录 - Dubbo 篇 1. 背景介绍 相关文档推荐: Dubbo 实战 - 服务降级 ...

  8. Spring Cloud 系列之 Dubbo RPC 通信

    Dubbo 介绍 官网:http://dubbo.apache.org/zh-cn/ Github:https://github.com/apache/dubbo 2018 年 2 月 15 日,阿里 ...

  9. Dubbo系列之 (一)SPI扩展

    一.基础铺垫 1.@SPI .@Activate. @Adaptive a.对于 @SPI,Dubbo默认的特性扩展接口,都必须打上这个@SPI,标识这是个Dubbo扩展点.如果自己需要新增dubbo ...

随机推荐

  1. 【BZOJ5019】[SNOI2017]遗失的答案(FWT,动态规划)

    [BZOJ5019][SNOI2017]遗失的答案(FWT,动态规划) 题面 BZOJ 题解 发现\(10^8\)最多分解为不超过\(8\)个本质不同质数的乘积. 而\(gcd\)和\(lcm\)分别 ...

  2. LOCALDB安装和连接

    关于LOCALDB的详细文档说明,包含安装,连接,共享连接等操作  https://technet.microsoft.com/zh-cn/hh510202 目的: 调试程序没有安装 sql serv ...

  3. 几个面试经典算法题Java解答

    题目一: public class testClockwiseOutput { //顺时针打印一个矩阵 @Test public void test(){ int[][] num = new int[ ...

  4. ASP: Response 对象 错误 'ASP 0251 : 80004005' 解决办法

    Response 对象 错误 'ASP 0251 : 80004005' 超过响应缓冲区限制 这种情况一般是因为需要输出的网页内容太大了,由于asp在输入内容到客户的浏览器上之前,会把需要输出的全部内 ...

  5. Kafka+Log4j2日志

    默认你已经安装配置了Zookeeper和Kafka. 为了目录清晰,我的Kafka配置文件的Zookeeper部分是:加上了节点用来存放Kafka信息 启动Zookeeper,然后启动Kafka. Z ...

  6. centos7 修改 PATH环境变量(注意,不是添加!!!TMD)

    起因都是,参照阿里云的Java环境配置,MMP~ 现在我们分析一下这几句话.JAVA_HOME和JRE_HOME都是没问题的 CLASSPATH:注意 [  lib$:JRE  ]这部分,Linux环 ...

  7. 深入flask中的request

    缘起 在使用flask的时候一直比较纳闷request是什么原理,他是如何保证多线程情况下对不同请求参数的隔离的. 准备知识 在讲request之前首先需要先理解一下werkzeug.local中的几 ...

  8. 利用U盘启动制作GHO镜像

    利用U盘启动制作GHO镜像 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. In a realproduction environment. 我们我们可能遇到频繁的安装系统,安装环境 ...

  9. 【小白技术笔记】保存皮皮虾APP无水印视频到手机相册,只需要三步 [技术干货]

    百万段友回皮皮虾,转身一变,都成了皮友.作为当年的资深段友,今天的皮友的我.看到好视频,经典视频,搞笑视频,就想保存一份到手机相册,然后皮皮虾啊皮皮虾,有个让人很讨厌的地方,保存视频的时候就有皮皮虾的 ...

  10. POJ 2247 Humble Numbers

    A number whose only prime factors are 2,3,5 or 7 is called a humble number. The sequence 1, 2, 3, 4, ...