Dubbo SPI 的使用方法(一)- 扩展点自动包装

开篇

前面有说到 Java SPI 的介绍与使用方法, 而本篇要说的 Dubbo SPI 是基于 Java SPI 的一个升级与改造(改善了部分缺点,增加了几个新玩法)。具体内容可以去看官网 Dubbo-SPI 部分

本文主要来讲下 Dubbo SPI 的部分使用方法。

另外,后续文章会补齐 Dubbo SPI 的其他用法以及 Dubbo SPI 部分的源码解析。

当然 官网 也有 Dubbo SPI 的使用说明与源码导读,可以自行选择。

正文

Dubbo SPI 的使用方法具体分为以下部分:

  • 基本使用
  • 扩展点自动包装
  • 扩展点自适应
  • 扩展点自动装配
  • 扩展点自动激活

本文先来介绍前两种使用方法,建议先看下 Java SPI 的介绍与使用方法,了解下 SPI 的机制及用途。

1. 基本使用

从这点来看,Dubbo SPI 从使用上与 JAVA SPI 并无很大差异。

主要区别在于:

JDK 标准的 SPI 会一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但如果没用上也加载,会很浪费资源。

而 Dubbo SPI 可以选择性实例化某个扩展接口实现类。

下面来看下写法上的差别,具体代码如下:

1.1 定义一个接口

注解中的 value 为 步骤 1.3 中配置的" 接口实现类的名称",比如@SPI("helloService"), 相当于指定默认的扩展实现类为
com.nimo.service.impl.HelloServiceImpl


// 差别一:Dubbo 需要 SPI 注解
@SPI
public interface HelloService {

    void sayHello(String name);

}
1.2 定义接口的实现类
public class HelloServiceImpl implements HelloService {
    @Override
    public void sayHello(String name) {
        System.out.println("hello, " + name);
    }
}

1.3 在 classpath 下创建如下文件
# 差别二:文件夹命名方式不同,以及文件内容格式不同
META-INF\dubbo\com.nimo.service.HelloService (以接口名全路径命名)

文件内容为:key-value 形式

helloService=com.nimo.service.impl.HelloServiceImpl
# 可以有多个实现
helloService1=com.nimo.service.impl.HelloServiceImpl1
helloService2=com.nimo.service.impl.HelloServiceImpl2
省略。。。。
1.4 程序入口

public class App 
{
    public static void main( String[] args )
    {
        // 差别三: API 不同
        ExtensionLoader<HelloService> extensionLoader = ExtensionLoader.getExtensionLoader(HelloService.class);
        // 通过指定扩展类名称y ,获取对应实例化对象
        // 这里 extensionLoader 可以把它当作一个 map
        // 如果参数为 ”true“,会加载默认的扩展类
        HelloService helloService = extensionLoader.getExtension("helloService");
        helloService.sayHello("xiaoming");
    }
}

运行结果:

hello, xiaoming

其实 ExtensionLoader 内部确实有很多 ConcurrentHashMap 容器,它们各司其职,具体的后面源码篇会详细说。

2. 扩展点自动包装

ExtensionLoader 在加载扩展点时,如果加载到的扩展点有拷贝构造函数,则判定为扩展点 Wrapper 类。

这个有点类似 AOP,看下具体代码和效果就明白了。

2.1 新增一个类

// 实现扩展接口以及如下模板的构造方法
public class HelloServiceImplWrapper implements HelloService {

    private HelloService helloService;

    public HelloServiceImplWrapper(HelloService helloService){
        this.helloService = helloService;
    }

    @Override
    public void sayHello(String name) {
        // 这里相当于对原有的 Service 进行了增强
        System.out.println("before");
        helloService.sayHello(name);
        System.out.println("after");
    }
}
2.2 修改 META-INF\dubbo\com.nimo.service.HelloService 文件内容
// 第二步,在原有增加部分内容,更改后如下:
helloService=com.nimo.service.impl.HelloServiceImpl
helloService=com.nimo.service.impl.HelloServiceImplWrapper

运行结果:

before
hello, xiaoming
after

总结

本文先引入 Dubbo SPI 的基本使用,然后介绍了其中一个高级玩法-扩展点自动包装,
它的作用正如官网所说,类似一个 AOP。

另外,通过 ExtensionLoader 获取扩展点的实现类的具体实例时,大致伪代码如下所示:

HelloService helloService = new HelloServiceImpl();
if (wrapper 存在) {
   helloService = wrapper; 
}
return helloService;

最后调用 sayHello方法时,就是调用的 wrapper.sayHello()

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值