Dubbo 源码原理-SPI

Dubbo SPI

简介

SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。SPI 机制在第三方框架中也有所应用,比如 Dubbo 就是通过 SPI 机制加载所有的组件。不过,Dubbo 并未使用 Java 原生的 SPI 机制,而是对其进行了增强,使其能够更好的满足需求。在 Dubbo 中,SPI 是一个非常重要的模块。基于 SPI,我们可以很容易的对 Dubbo 进行拓展。如果大家想要学习 Dubbo 的源码,SPI 机制务必弄懂。 摘自dubbo 官方文档

能够被扩展的接口必须要有这样的标记->@SPI{} (Dubbo自定义的注解)
@SPI(‘value’) 表示当前扩展点的默认实现

静态扩展点

1、解析 load 指定路径下对应的SPI 扩展点的实现,缓存到hashmap中,key 就是配置文件中定义的name,value就是class
2、getExtension(‘name’)->EXTENSION_INSTANCES.get(‘name’) 获取 instance

依赖注入

Spring中依赖注入的方式:

  • 接口注入
  • setter注入
  • 构造方法注入

Dubbo 依赖注入的方式:

set方法进行注入
如果当前的扩展点中依赖其他的扩展点,会进行依赖注入

public class ZookeeperDynamicConfigurationFactory extends AbstractDynamicConfigurationFactory {

    //扩展点接口
    private ZookeeperTransporter zookeeperTransporter;

    //通过set注入
    public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) {
        this.zookeeperTransporter = zookeeperTransporter;
    }

    @Override
    protected DynamicConfiguration createDynamicConfiguration(URL url) {
        return new ZookeeperDynamicConfiguration(url, zookeeperTransporter);
    }
}

自适应扩展点

@Adaptive
两种实现方式:、

类的实现方式

提前写好了一个自适应的扩展点->主要目的就是针对具体的实现进行适配
在这里插入图片描述

org.apache.dubbo.common.extension.ExtensionLoader

private ExtensionLoader(Class<?> type) {
   this.type = type;
   objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
方法的实现方式

org.apache.dubbo.rpc.Protocol

 @Adaptive
 <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;

在这里插入图片描述

激活扩展点

@Activate(group = {CONSUMER, PROVIDER}, value = CACHE_KEY)

org/apache/dubbo/common/extension/ExtensionLoader

/**
 * Get activate extensions.
 *
 * @param url    url
 * @param values extension point names
 * @param group  group
 * @return extension list which are activated
 * @see org.apache.dubbo.common.extension.Activate
 */
public List<T> getActivateExtension(URL url, String[] values, String group) {
    List<T> exts = new ArrayList<>();
    List<String> names = values == null ? new ArrayList<>(0) : Arrays.asList(values);
    if (!names.contains(REMOVE_VALUE_PREFIX + DEFAULT_KEY)) {
        getExtensionClasses();
        for (Map.Entry<String, Object> entry : cachedActivates.entrySet()) {
            String name = entry.getKey();
            Object activate = entry.getValue();

            String[] activateGroup, activateValue;

            if (activate instanceof Activate) {
                activateGroup = ((Activate) activate).group();
                activateValue = ((Activate) activate).value();
            } else if (activate instanceof com.alibaba.dubbo.common.extension.Activate) {
                activateGroup = ((com.alibaba.dubbo.common.extension.Activate) activate).group();
                activateValue = ((com.alibaba.dubbo.common.extension.Activate) activate).value();
            } else {
                continue;
            }
            if (isMatchGroup(group, activateGroup)
                    && !names.contains(name)
                    && !names.contains(REMOVE_VALUE_PREFIX + name)
                    && isActive(activateValue, url)) {
                exts.add(getExtension(name));
            }
        }
        exts.sort(ActivateComparator.COMPARATOR);
    }
    List<T> usrs = new ArrayList<>();
    for (int i = 0; i < names.size(); i++) {
        String name = names.get(i);
        if (!name.startsWith(REMOVE_VALUE_PREFIX)
                && !names.contains(REMOVE_VALUE_PREFIX + name)) {
            if (DEFAULT_KEY.equals(name)) {
                if (!usrs.isEmpty()) {
                    exts.addAll(0, usrs);
                    usrs.clear();
                }
            } else {
                usrs.add(getExtension(name));
            }
        }
    }
    if (!usrs.isEmpty()) {
        exts.addAll(usrs);
    }
    return exts;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值