dubbo spi extensionloader 插件化

SPI

SPI只是一种协议,它只是规定在META-INF目录下提供接口的实现描述文件,由框架本身定义接口、规范,第三方只需要将自己实现在META-INF下描述清楚,那么框架就会自动加载你的实现。比如Dubbo的规则是在META-INF/dubbo、META-INF/dubbo/internal或者META-INF/services下面以需要实现的接口全面去创建一个文件,并且在文件中以properties规则一样配置实现类的全面以及分配实现一个名称。

 

ExtensionLoader

Dubbo对于SPI的实现全部集中在类ExtensionLoader中,ExtensionLoader是一个单例工厂类,它对外暴露getExtensionLoader静态方法返回一个ExtensionLoader实体,这个方法的入参是一个Class类型,这个方法的意思是返回某个接口的ExtensionLoader,对于一个接口,只会有一个ExtensionLoader实体。

ExtensionLoader实体对外暴露一些接口来获取扩展实现,这些接口分为几类,分别是activate extension, adaptive extension, default extension, get extension by name , supported extension。

 

(1)URL为总线的模式

即运行过程中所有的状态信息都可以通过URL来获取。

(2)activate extension

activate extension都需要传入url参数,这里涉及到Activate 注解,这个注解主要用于标注在插件接口实现类上,用来配置该扩展实现类激活条件

在Dubbo框架里 面的Filter的各种实现类都通过Activate标注,用来描述该Filter什么时候生效。

 

  • MonitorFillter通过Activate标注来告诉Dubbo框架这个Filter是在服务提供端和消费端会生效的。
  • TimeoutFilter则只在服务提供端生效。
  • ValidationFilter除了在消费端和服务提供端激活,它还配置value,这是另一个激活条件,这个value表示传入的URL参数中必须有指定的值才可激活这个扩展。

另个activate注解还有一个参数order,这是表示一种排序规则,因为一个接口的实现有多种,返回的结果是一个列表,如果不指定排序规则,那么可能列表的排序不可控,其中order的值越大,那么该扩展实现排序就越靠前,对于排序还可以使用before和after来配置。对于用户自定义的扩展默认是追加到列表后面的。

 

getActivateExtension(URL url, String[] values, String group)

(3)adaptive extension

Dubbo框架提供的各种接口均有很多种类的实现,为了能够适配一个接口的各种实现,便有了adaptive extension。createAdaptiveExtensionClassCode。

  • 对某个接口实现对应的适配器。

对于这种途径,Dubbo也提供了一个注解Adaptive,用来标注在接口的某个实现上,表示这个实现并不是提供具体业务支持,而是作为该接口的适配器。

Dubbo框架中的AdaptiveExtensionFatory就是使用Adaptive进行了标注,它用来适ExtensionFactory接口SPIExtensionFactory和SpringExtensionFactory两种实现 ,它会根据支行的状态来确定具体调用ExtensionFactory的哪个实现。

  • Dubbo框架动态生成适配器。

ExtensionLoader通过分配接口配置的adaptive规则动态生成adaptive类并且加载到ClassLoader中,来实现动态适配。adaptive注解有一个value属性,通过设置这个属性便可以设置该接口的Adaptive的规则,Dubbo动态生成Adaptive的扩展接口的方法入参必须包含URL或者参数存在能返回URL对象的方法,这样才能根据支行状态动态选择具体实现。

 

(4)get extension by name

就是通过接口实现的别名来获取某个具体的服务。

 

(5)default extension

被实现的接口必须标注SPI注解,用来告诉Dubbo这个接口是通过SPI来进行扩展实现的,在接口上标注SPI注解的时候可以配置一个value属性用来描述这个接口的默认实现别名。

 

应用场景

在dubbo中随处可见ExtensionLoader的使用,几乎任何预留扩展的服务都通过ExtensionLoader加载。

  • SPI,扩展点接口标识,只有添加了这个注解才能通过ExtensionLoader加载其服务实现。
  • Adaptive,标识此类为Adaptive类(dubbo可自动生成)。
  • Activate,用于标识此实现是否激活,可以配置一些激活条件。

以ReferencConfig为例,其中的Protocol等便是通过ExtensionLoader来加载的。

 

(1)首先通过getExtensionLoader方法获取对应的Protocol的ExtensionLoader实例。

(2)之后便是通过getAdaptiveExtension()获取对应的Adaptive实现。

(3)Adaptive实例不存在,则通过createAdaptiveExtension()创建,在这之前要加载Adaptive Class。

(4)如果找不到被Adaptive注解的适配器,则通过dubbo动态创建(字节码)适配器。

(5)由injectExtension完成依赖服务注入(借助ExtensionFactory找到依赖的服务,通过set方法注入)。

 

 

Dubbo的扩展点主要有adaptive和wrapper两种:

(1)adaptive,因为dubbo底层会大量使用反射,出于性能考虑默认使用javassist字节码编译生成一个adaptive,由它动态委派处理。用户可以自己实现一个adaptive,只需要对某个类打上@adaptive即可。对于默认编译生成Adaptive的方案,需要使用@Adaptive声明接口上的哪些方法是adaptive方法。扩展点名称的key默认是接口类型上@SPI#value,方法上的@Adaptive#value有更高优先级。

(2)包装类必须有一个参数为spi接口类型的构造函数,否则不能正常工作。判断warpper的标准是class有没有一个参数为接口类型的构造参数。Wrapper可以有多个,会被按顺序依次覆盖,假设spi定义如下:

A=a.b.c

B=a.b.wrapper1

C=a.b.wrapper2

wrapper的最终结构则为B-C-A

 

最后欢迎大家访问我的个人网站:1024s

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值