dubbo中自己实现了一套SPI,解决了dubbo的可扩展性问题,方便了框架的各层可以在多个不同的实现之间进行来回切换。
SPI的实现主要在类ExtensionLoader中,这个类的构造函数接收一个Class类型的参数,并且这个class必须是接口,必须用注解spi进行标注。有多少个可扩展接口,就有多少个ExtensionLoader的实例。
这个类中一共有三类方法:根据名字获取实现、获取某个接口的适配实现和获取某个接口的激活实现
1、根据名字获取实现
这类方法比较好理解,如下Protocol有下面这么多的实现:
等号前面的是名字,等号后面的是实现,例如:如果传入dubbo就会返回DubboProtocol
下面对这个方法的源码进行分析
这个方法比较好理解,其实就是判断缓存,如果有直接返回,没有的话通过createExtension方法进行创建
第499行调用getExtensionClasses(),会返回这个接口的所有实现,这个方法的内部会有扫描三个目录进行初始化的过程。
第509行的injectExtension方法的主要作用是对获取到的这个实现的内部的属性字段进行赋值。就是如果这个类中有的字段的类型是SPI接口或者在spring容器中可以找到对应的ben,那么就对这些字段进行赋值。
第510到515行是对当前返回的实例进行再次包装,当然是如果这个spi接口的实现有包装类的话。如果某个实现类,有单个参数的构造函数,并且参数类型是当前SPI接口,那么这个类就是包装类。他就好对当前
要返回的类,进行包装,有可能存在多个包装器类。例如上面第一张截图中的ProtocolFilterWrapper和ProtocolListenerWrapper就是两个包装器类
总结一下:
(1)初始化当前spi接口的所有实现(会扫描三个目录)到内存中
(2)根据名字返回对应的实现的实例
(3)对这个实例进行属性字段的赋值,来源于其他的spi实现或者spring容器
(4)如果当前spi接口有包装器类,对当前实现进行包装,有可能有多个包装器类
这类方法基本是不会被外面的类调用,主要是为另外两类方法服务
2、获取SPI接口的适配实现,只会返回一个实现类。
这个方法要@Adaptive注解配合实现。这个注解可以标注在类上,也可以标注在方法上,如果是标注在方法上只能是接口方法不是类方法。
(1)如果某个SPI接口的实现类,被这个注解进行了标注,那么直接返回这个实现类
(2)如果接口的方法被这个注解进行了标注,那么会利用字节码进行动态生成一个类。
如果接口像下面这么标注
那么动态生成的方法将会是下面这样
由于某个SPI接口的适配实现只会有一个,所有(1)的优先级大于(2),获取适配实现主要是解决,只有在程序运行期间才能却能使用哪个实现
3、获取SPI接口的激活实现,可以是多个
最常见的例子就是获取Filter
激活某个实现有两种方式
(1)使用注解Activate进行标注,这个注解有两个重要的参数一个是group,一个是value。这两个参数都是数组
group表示getActivateExtension方法传入的grop值如果被注解上的group数组包含,那么返回这个扩展。
value表示URL的parameter参数中,如果有一个参数的key和value数组的任何一个元素相同,那么返回这个扩展。
group和value不知道,表示不做约束,无条件激活这个实现
(2)不通过注解标注还可以在URL参数中指定实现类的名字,这个方法既可以激活某个实现,也可以去掉(1)中已经激活的实现,例如下面这个配置filter的例子
总结一下:
(1)通过注解进行标注的实现,被称为缺省扩展,包括dubbo自带的(入各种filter)和用户自定义的扩展用注解进行了标注。
(2)通过url的参数来指定实现的名字,也可以激活某个或某些实现。
(3)url的参数也可以去掉缺省扩展,规则见上面的图。
下面分析下代码:
第196行表示没有去掉全部的缺省扩展
198行变量所有的通过注解进行标注的实现
201行grop可以匹配上
203、204、205判断这个缺省扩展没有通过URL的参数去掉,isActivate判断注解的value值中任意一个元素和RUL参数的任意一个key相同
206表示此扩展被激活了,添加到list中
210排序
上面这部分代码,就是在url参数中指定扩展名字是的处理逻辑
215、216行表示没有在url参数中排除这个扩展
217就是处理和缺省扩展的排序关系
相关推荐
【标题】"仿Dubbo的ExtensionLoader"是一个项目,它旨在模仿Dubbo框架中的ExtensionLoader机制。这个机制是Dubbo核心设计模式之一,用于实现插件化和扩展性。Dubbo是一个高性能、轻量级的Java远程服务调用框架,其...
在Dubbo框架中,`loadbalance`配置是用来指定负载均衡策略的,允许用户自定义或者选择内置的策略,如Random、RoundRobin等,以决定如何在服务提供者之间分配消费者请求。然而,当用户报告`loadbalance`配置不生效时...
Dubbo传输层实现是Dubbo框架中的核心组件之一,它负责在服务提供者和服务消费者之间建立高效的通信链路。在Dubbo中,传输层扮演着数据传输媒介的角色,确保请求和响应能够在分布式环境中准确无误地传递。在这个实现...
例如,Dubbo中的`ExtensionLoader`类就实现了SPI的思想。当Dubbo需要某个接口的实现时,它会通过`ExtensionLoader`来加载这些实现。这种方式不仅使得Dubbo能够轻松地添加新的扩展点,也确保了核心代码的简洁性。 ##...
Dubbo采用了Spring的ExtensionLoader实现Service Provider Interface(SPI)机制,允许开发者方便地扩展和替换Dubbo的组件。开发者可以通过定义接口,并在配置文件中指定实现类,即可在运行时动态加载对应的实现,极...
在dubbo中,ExtensionLoader是一个重要的组件,负责加载和管理扩展点。ExtensionLoader使用了工厂模式,提供了一个统一的接口来管理扩展点。在ProtocolListenerWrapper的实现中,我们可以看到ExtensionLoader被用于...
Dubbo SPI(Service Provider Interface)是阿里巴巴开源的分布式服务框架Dubbo中的一个重要特性,它提供了一种服务发现和服务实现动态加载的方式。通过SPI机制,Dubbo可以灵活地扩展其功能,使得开发者能够按照自己...
1. **ExtensionLoader**:这是Dubbo SPI的核心类,负责加载服务实现。它会缓存已加载的服务,避免重复加载,并提供获取默认服务、所有服务实例、按条件过滤服务等方法。 2. **AdaptiveExtension**:适应性扩展是...
ExtensionLoader和InterfaceMetadata类是Dubbo实现SPI的核心。 总结,Dubbo 2.5.4的源码解析是一次深入了解分布式服务治理的旅程。通过对源码的分析,我们可以掌握Dubbo如何高效地处理服务的注册、发现、调用,以及...
`ExtensionLoader`是Dubbo实现SPI的关键组件,它使得Dubbo具有良好的可扩展性和灵活性。 总结,Dubbo的源码学习不仅可以帮助我们理解分布式服务治理的实现原理,还能提升我们的系统设计能力。通过深入分析`Provider...
源码解析将介绍`META-INF/services`目录下的配置文件以及`com.alibaba.dubbo.common.extension.ExtensionLoader`类的作用。 通过阅读《Dubbo源码解析2.0》文档,开发者不仅可以深入了解Dubbo的设计理念,还能掌握其...
`com.alibaba.dubbo.common.extension.ExtensionLoader`类是SPI的核心实现,通过它可以加载和管理所有的扩展类。 9. **配置管理** 配置管理是Dubbo的重要组成部分,`com.alibaba.dubbo.config.Configuration`接口...
`ExtensionLoader`类是SPI的核心,负责加载和管理扩展。开发者可以根据需要扩展`Protocol`、`Registry`、`Filter`等接口。 总结,Dubbo源码(注释版)提供了全面的内部实现细节,帮助开发者深入理解分布式服务治理...
这些协议的实现类都会被**Dubbo**的`ExtensionLoader`加载,从而确保框架可以根据配置选择正确的协议进行网络通信。 #### 四、**Dubbo**中的粘包和拆包问题 在**Dubbo**中,通信层通常使用**Netty**作为NIO框架来...
首先,让我们理解Invoker在Dubbo中的角色。Invoker是Dubbo领域模型的核心组件,它代表了服务的调用者,封装了服务的调用逻辑。当服务提供者启动时,Dubbo会创建一个Invoker实例,这个实例包含了服务提供者的具体实现...
在本节课中,我们将探讨 Dubbo 的几个核心特性以及其实现机制。 首先,我们回顾了上堂课的内容,其中包括: 1. **异步调用 - Future 模式**:在 Dubbo 中,通过 Future 模式可以实现调用的异步化。调用方发起请求...
不同于普通的概念介绍或功能概述,本文聚焦于技术实现细节,旨在帮助中高级软件开发工程师理解Dubbo框架内部如何处理Filter和Listener的集成。 #### 问题背景 在Dubbo消费方执行流程中,看似并没有直接涉及到...
在Dubbo SPI的实现中,`getExtensionLoader(Class)`方法是获取指定接口的ExtensionLoader实例的关键。一旦获取到ExtensionLoader,就可以通过`getExtension(String name)`方法获取名为"name"的具体扩展点实现。例如...
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension("dubbo"); Invoker<DemoService> invoker = protocol.export(newInvokerAdapter(new DemoServiceImpl(), url)); // ...
- Dubbo提供了一个更简单直观的方法`getExtension`来获取SPI服务实例,例如`ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(key)`即可根据key获取对应的服务实现。 4. **增强AOP支持**: - 在...