文档章节

Dubbo SPI 之 @Activate注解使用和实现解析

键走偏锋
 键走偏锋
发布于 06/25 13:28
字数 1178
阅读 51
收藏 0
点赞 0
评论 0

Activate注解标识一个扩展是否被激活和使用,可以放在定义的类上和方法上,dubbo用它在SPI扩张类定义上,标识这个扩展实现激活的条件和时机,先看下定义:


/**
 * Activate
 * <p/>
 * 对于可以被框架中自动激活加载扩展,此Annotation用于配置扩展被自动激活加载条件。
 * 比如,过滤扩展,有多个实现,使用Activate Annotation的扩展可以根据条件被自动加载。
 * <ol>
 * <li>{@link Activate#group()}生效的Group。具体的有哪些Group值由框架SPI给出。
 * <li>{@link Activate#value()}在{@link com.alibaba.dubbo.common.URL}中Key集合中有,则生效。
 * </ol>
 * <p>
 * <p/>
 * 底层框架SPI提供者通过{@link com.alibaba.dubbo.common.extension.ExtensionLoader}的{@link ExtensionLoader#getActivateExtension}方法
 * 获得条件的扩展。
 *
 * @author william.liangf
 * @author ding.lid
 * @export
 * @see SPI
 * @see ExtensionLoader
 * @see ExtensionLoader#getActivateExtension(com.alibaba.dubbo.common.URL, String[], String)
 */
@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://my.oschina.net/u/146130/blog/1789814

共有 人打赏支持
键走偏锋
粉丝 62
博文 526
码字总数 572737
作品 0
通州
程序员
动手学dubbo之Container与SPI

在动手学dubbo之初体验一文中我们了解了dubbo的架构,接下来的几篇文章我会根据阅读Quick Start里面的demo源码来深入学习dubbo的实现。这一篇主要学习Container的原理、实现和作用。 一、从启...

ginobefun
2017/07/13
0
0
dubbo源码分析系列——dubbo的SPI机制源码分析

dubbo的SPI机制 关于dubbo的SPI机制请参阅dubbo开发者文档 -> http://dubbo.io/Developer+Guide-zh.htm#DeveloperGuide-zh-%E6%89%A9%E5%B1%95%E7%82%B9%E5%8A%A0%E8%BD%BD 我只把我自己理解......

杨武兵
2016/06/05
462
4
dubbo @Activate 注解使用和实现解析

Activate注解表示一个扩展是否被激活(使用),可以放在类定义和方法上,dubbo用它在spi扩展类定义上,表示这个扩展实现激活条件和时机。先看下定义: 它有两个设置过滤条件的字段,group,value...

wannshan
04/04
0
0
Dubbo SPI之Adaptive详解

前期准备 一. 增加pom 二. 添加代码 1. shuqi.dubbotest.spi.adaptive.AdaptiveExt2 作为需要被扩展的接口,注意要加上@SPI注解 2. 上面接口的三个实现类 a. shuqi.dubbotest.spi.adaptive....

数齐
05/01
0
0
从ExtensionLoader看Dubbo插件化

欢迎加入DUBBO交流群:259566260 之前很多人问我Dubbo插件化是怎么实现的,我都是简单回答SPI。了解SPI的人知道,它只是提供一种协议,并没有提供相关插件化实施的接口,不像OSGI那样有一成套...

Bieber
2015/05/23
0
14
dubbo扩展的实现原理

1 概要介绍及使用方法 1.1 Java SPI 关于 java spi 的介绍可以参见下面这个帖子 http://singleant.iteye.com/blog/1497259 Dubbo的扩展点加载从JDK标准的SPI(Service Provider Interface)扩展...

万里路遥
2016/06/28
489
1
Dubbo SPI之Activate详解

前期准备 一. 增加pom 二. 添加代码 重要声明:本节演示的源码来自于网络的一片文章,看例子讲解的很透彻,很能说明问题就直接引用过来了,没法注明出处,如果有知道的请和我联系下,我添加上...

数齐
05/01
0
0
dubbo源码分析系列(1)扩展机制的实现

1 系列目录 - dubbo源码分析系列(1)扩展机制的实现- dubbo源码分析系列(2)服务的发布- dubbo源码分析系列(3)服务的引用- dubbo源码分析系列(4)dubbo通信设计 2 SPI扩展机制 站在一个...

乒乓狂魔
2015/09/21
8.6K
5
Dubbo的Filter执行顺序分析

最近用到了Dubbo的Filter来做一些监控的东西,顺便整理了一下dubbo中的Filter调用顺序及如何确定的。 服务提供方的过滤器被调用顺序: EchoFilter->ClassLoaderFilter->GenericFilter->Cont...

宸明
01/23
0
0
dubbo源码解析-spi(二)

前言 上一篇简单的介绍了的基本一些概念,在末尾也提到了,对jdk的spi进行了一些改进,具体改进了什么,来看看文档的描述 JDK 标准的 SPI 会一次性实例化扩展点所有实现,如果有扩展实现初始化很...

肥朝
01/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

华为nova3超级慢动作酷玩抖音,没有办法我就是这么强大

华为nova3超级慢动作酷玩抖音,没有办法我就是这么强大!华为nova3超级慢动作酷玩抖音,没有办法我就是这么强大! 在华为最新发布的nova 3手机上,抖音通过华为himedia SDK集成了60fps、超级...

华为终端开放实验室
20分钟前
0
0
多 SSH Key 实现同一台服务器部署多 Git 仓库

本文以以下需求为背景,介绍详细的做法: 需在同一台服务器同时部署两个不同的 Github 仓库(对 Bitbucket 等 git 服务同样适用) root 用户可在远程登录 SSH 后附上预期的 SSH Key 进行 gi...

yeahlife
23分钟前
0
0
003. es6数值的扩展

一、普通扩展 Number 方法,将字符串、数值转为十进制 : Number('0b111') Number.isFinite() 用来检查一个数值是否为有限的:Number.isFinite(15) Number.isNan() 用来检查一个值是否为NaN N...

秋季长青
37分钟前
0
0
rabbitmq学习(二)

基本队列:Producer直接发送信息到Queue中,Consumer接收Queue发送过来的信息 简而言之,一个生产者发送信息,一个消费者接收信息。 获取连接工具类: package com.example.demo.utils;i...

人觉非常君
41分钟前
0
0
C语言数组和指针的语法糖

对于C语言,我可以这样秀:比如当创建一个数组arr[n]之后,一般我们去遍历数组的时候是for (int i = 0; i < n; i++) { a[i]; }但是我知道下表访问符[]是个语法糖,也就是说a[i]在编译器看来是...

ustbgaofan
45分钟前
0
0
Call to undefined function bcmath()的解决方法

乐意黎的ECS主机环境,Centos7.2 + PHP7 由于使用了bcdiv()函数,运行时总在抛错。 Fatal error: Call to undefined function bcmath() in /usr/loca/apache/htdocs/... on line 4 一查得知:......

dragon_tech
51分钟前
0
0
css优先级

..

architect刘源源
55分钟前
0
0
【转】Twitter的分布式自增ID算法snowflake

结构 snowflake的结构如下(每部分用-分开): 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 第一位为未使用,接下来的41位为毫秒级时间(41位的长度可以...

talen
59分钟前
0
0
hive支持行级修改

Hive从0.14版本开始支持事务和行级更新,但缺省是不支持的,需要一些附加的配置。要想支持行级insert、update、delete,需要配置Hive支持事务。 一、Hive具有ACID语义事务的使用场景 1. 流式...

hblt-j
今天
0
0
Python---scrapy框架的学习

scrapy框架的学习 先熟悉下scrapy项目结构: scrapyTest/scrapyTest/ _init_.py用来初始化项目信息 scrapyTest/scrapyTest/ items.py文件为爬虫项目的数据容器文件,主要用来定义我们的数据....

android-key
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部