Dubbo扩展点SPI实践示例解析

 更新时间:2022年10月19日 16:16:22   作者:UniJoy  
这篇文章主要为大家介绍了Dubbo扩展点SPI实践示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

正文

Dubbo的扩展点加载从JDK标准的SPI(Service Provider Interface)扩展点发现机制加强而来。Dubbo改进了JDK标准的SPI的以下问题:

  • JDK标准的SPI会一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但如果没用上也加载,会很浪费资源。如果扩展点加载失败,连扩展点的名称都拿不到了。
  • Dubbo增加了对扩展点IoC和AOP的支持,一个扩展点可以直接setter注入其它扩展点。 比如:Filter是Dubbo的集合类扩展点的一种,还有其他如InvokerListener, ExportListener, TelnetHandler, StatusChecker等扩展,这个有时间可以都看看(搜索Dubbo开发者指南:SPI参考手册)

扩展点配置:

src\
 |-main\
    |-java\
        |-com\
            |-xxx\
                |-XxxFilter.java (实现Filter接口)\
    |-resources\
        |-META-INF\
            |-dubbo\
                |-com.alibaba.dubbo.rpc.Filter (纯文本文件,内容为:xxx=com.xxx.XxxFilter)

扩展实现类:

@Activate
public class AuthorityFilter implements Filter {
    private static Logger logger = LoggerFactory.getLogger(AuthorityFilter.class);
    List<String> ipWhiteList = AuthorityUtils.getAccessListByKey("1");
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        [logger.info](http://logger.info/)("########go into filtersuccess !!########");
        String clientIp = RpcContext.getContext().getRemoteHost();
        String host = IpParseUtils.getHostByIp(clientIp);
        if (ipWhiteList.contains(host))
Unknown macro: {            [logger.info](http://logger.info/)("########白名单校验通过!########");            return invoker.invoke(invocation);        }
else
Unknown macro: {            [logger.info](http://logger.info/)("########白名单校验未通过!########");            return new RpcResult();        }
    }
}

拦截配置文件:

在扩展类的jar包内,放置扩展点配置文件:META-INF/dubbo/接口全限定名,内容为:配置名=扩展实现类全限定名,多个实现类用换行符分隔。(注意:这里的配置文件是放在你自己的jar包内,不是dubbo本身的jar包内,Dubbo会全ClassPath扫描所有jar包内同名的这个文件,然后进行合并)

注意这个xxx=左侧的名字跟你扩展类同名哦(这是个坑儿,别问我怎么知道的)!

AuthorityFilter=your.extend.dubbo.async.provider.AuthorityFilter

调用拦截扩展:

<dubbo:provider filter="AuthorityFilter"></dubbo:provider>

拦截扩展说明:

服务提供方和服务消费方调用过程拦截,Dubbo本身的大多功能均基于此扩展点实现,每次远程方法执行,该拦截都会被执行,请注意对性能的影响。\

常用约定:

  • 用户自定义filter默认在内置filter之后。
  • 特殊值default,表示缺省扩展点插入的位置。 比如:filter="xxx,default,yyy",表示xxx在缺省filter之前,yyy在缺省filter之后。\
  • 特殊符号-,表示剔除。
    比如:filter="-foo1",剔除添加缺省扩展点foo1。
    比如:filter="-default",剔除添加所有缺省扩展点。\
  • provider和service同时配置的filter时,累加所有filter,而不是覆盖。
    比如:<dubbo:provider filter="xxx,yyy"/>和<dubbo:service filter="aaa,bbb" />,则xxx,yyy,aaa,bbb均会生效。
    如果要覆盖,需配置:<dubbo:service filter="-xxx,-yyy,aaa,bbb" />\

实现细节:

  • 解析服务

基于dubbo.jar内的META-INF/spring.handlers配置,Spring在遇到dubbo名称空间时,会回调DubboNamespaceHandler。

所有dubbo的标签,都统一用DubboBeanDefinitionParser进行解析,基于一对一属性映射,将XML标签解析为Bean对象。

在ServiceConfig.export()或ReferenceConfig.get()初始化时,将Bean对象转换URL格式,所有Bean属性转成URL的参数。

然后将URL传给Protocol扩展点,基于扩展点的Adaptive机制,根据URL的协议头,进行不同协议的服务暴露或引用。

  • 拦截服务

基于扩展点的Wrapper机制,所有的Protocol扩展点都会自动套上Wrapper类。

基于ProtocolFilterWrapper类,将所有Filter组装成链,在链的最后一节调用真实的引用。

基于ProtocolListenerWrapper类,将所有InvokerListener和ExporterListener组装集合,在暴露和引用前后,进行回调。

包括监控在内,所有附加功能,全部通过Filter拦截实现。

还有暴露服务和引用服务,个人觉得看这上面这两个对写程序相对更有用些!

扩展点的几个特点:

扩展点自动包装

自动Wrap扩展点的Wrapper类

ExtensionLoader会把加载扩展点时(通过扩展点配置文件中内容),如果该实现有拷贝构造函数,则判定为扩展点Wrapper类。Wrapper类同样实现了扩展点接口。

扩展点自动装配

加载扩展点时,自动注入依赖的扩展点

加载扩展点时,扩展点实现类的成员如果为其它扩展点类型,ExtensionLoader在会自动注入依赖的扩展点。

ExtensionLoader通过扫描扩展点实现类的所有set方法来判定其成员。即ExtensionLoader会执行扩展点的拼装操作。

ExtensionLoader加载CarMaker的扩展点实现RaceCar时,setWheelMaker方法的WheelMaker也是扩展点则会注入WheelMaker的实现。

扩展点自适应

扩展点的Adaptive实例
ExtensionLoader注入的依赖扩展点是一个Adaptive实例,直到扩展点方法执行时才决定调用是一个扩展点实现。

  • Dubbo使用URL对象(包含了Key-Value)传递配置信息

扩展点方法调用会有URL参数(或是参数有URL成员)

这样依赖的扩展点也可以从URL拿到配置信息,所有的扩展点自己定好配置的Key后,配置信息从URL上从最外层传入。URL在配置传递上即是一条总线。

示例:有两个为扩展点CarMaker(造车者)、wheelMaker(造轮者)

扩展点自动激活

对于集合类扩展点,比如:Filter, InvokerListener, ExportListener, TelnetHandler, StatusChecker等,可以同时加载多个实现,此时,可以用自动激活来简化配置,如:

import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.Filter;
@Activate // 无条件自动激活
public class XxxFilter implements Filter {
    // ...
}

以上就是Dubbo扩展点SPI实践示例解析的详细内容,更多关于Dubbo扩展点SPI实践的资料请关注脚本之家其它相关文章!

相关文章

  • 解决Spring boot整合mybatis,xml资源文件放置及路径配置问题

    解决Spring boot整合mybatis,xml资源文件放置及路径配置问题

    这篇文章主要介绍了解决Spring boot整合mybatis,xml资源文件放置及路径配置问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Java8新特性之新日期时间库的使用教程

    Java8新特性之新日期时间库的使用教程

    这篇文章主要给大家介绍了关于Java8新特性之新日期时间库使用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • SpringBoot thymeleaf eclipse热部署方案操作步骤

    SpringBoot thymeleaf eclipse热部署方案操作步骤

    今天小编就为大家分享一篇关于SpringBoot thymeleaf eclipse热部署方案操作步骤,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • IDEA中没有Mapper.xml模板选项的处理方法

    IDEA中没有Mapper.xml模板选项的处理方法

    这篇文章主要介绍了IDEA中没有Mapper.xml模板选项的处理方法,需其实解决方法很简单,只需要在idea中导入模板即可,本文图文的形式给大家分享解决方法,需要的朋友可以参考下
    2021-04-04
  • Java实现的Base64加密算法示例

    Java实现的Base64加密算法示例

    这篇文章主要介绍了Java实现的Base64加密算法,结合实例形式分析了Java实现的base64编码转换相关使用方法及操作注意事项,需要的朋友可以参考下
    2018-04-04
  • 消息队列 RabbitMQ 与 Spring 整合使用的实例代码

    消息队列 RabbitMQ 与 Spring 整合使用的实例代码

    本篇文章主要介绍了消息队列 RabbitMQ 与 Spring 整合使用的实例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • netty中的IO、NIO、AIO使用详解

    netty中的IO、NIO、AIO使用详解

    这篇文章主要介绍了netty中的IO、NIO、AIO使用详解,本文会说明各种IO的特点、分别解决了什么样的问题做一个分析阐述,并结合Java代码例子来辅助理解,像这些的历史演进和详细的底层原理网上很多,所以我们只站在应用层,使用者的角度去分析,需要的朋友可以参考下
    2023-12-12
  • Mybatis-Plus分页的使用与注意事项

    Mybatis-Plus分页的使用与注意事项

    分页查询每个人程序猿几乎都使用过,下面这篇文章主要给大家介绍了关于Mybatis-Plus分页的使用与注意事项的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-04-04
  • Spring框架开发scope作用域分析总结

    Spring框架开发scope作用域分析总结

    这篇文章主要介绍了Spring框架开发中scope作用域的分析总结,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2021-09-09
  • Java稀疏数组详细图文教程

    Java稀疏数组详细图文教程

    当一个数组中的大部分元素为相同的值,可使用稀疏数组来保存该数组,可以将稀疏数组看做是普通数组的压缩,这篇文章主要给大家介绍了关于Java稀疏数组的相关资料,需要的朋友可以参考下
    2023-09-09

最新评论