【最新Dubbo3深入理解】Dubbo3中的SPI机制以及IOC、AOP

本文详细介绍了Dubbo3中的SPI机制,包括其原理、与JavaSPI的对比,以及Dubbo如何通过自定义机制实现更灵活的扩展、依赖注入和AOP。讨论了Dubbo为何选择不使用Java原生SPI,并列举了DubboSPI的优势和改进之处。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术的推送!

在我后台回复 「资料」 可领取编程高频电子书
在我后台回复「面试」可领取硬核面试笔记

文章导读地址:点击查看文章导读!

感谢你的关注!

最新 Dubbo3 深入理解原理系列

在这里插入图片描述

Dubbo 的 SPI 机制

SPI 机制原理介绍

在 Dubbo 中 SPI 是一个非常重要的模块,基于 SPI 可以很容易的进行扩展,可以 很灵活的替换接口的实现类通过 SPI 可以在运行期间动态的寻找具体的实现类!

并且 Dubbo 的 SPI 还实现了自己的 IOC 和 AOP!

其实 SPI 的原理很简单,就是我们定义一个接口 UserService,在定义一个配置文件(假设为文件 a),此时假设 UserService 有两个实现类:UserServiceImpl1、UserServiceImpl2,用户根据自己的需求在文件 a 中指定需要加载哪一个实现类,如下:

# 指定接口对应实现类的全限定类名
com.example.hello.UserService=com.example.hello.impl.UserServiceImpl1

image-20240219140242325

像 Java 中也提供了 SPI 机制,但是 Dubbo 中并没有使用 Java 提供的 SPI ,而是 基于 Java 提供的 SPI 实现了一套功能更强的 SPI 机制!

Dubbo 中通过 SPI 指定实现类的配置文件放在 META-INF/dubbo 路径下(一般 SPI 机制的配置文件都在 META-INF 目录下)

Dubbo 为什么不用 JDK 中的 SPI 而是自己实现一套呢?

其实很容易想到,为什么不用呢,就是因为太弱了!

JDK 提供的 SPI 机制不满足 Dubbo 的需求,因此 Dubbo 才要开发自己的 SPI 机制

回答的思路就是,先说 JDK 的 SPI 哪里不满足呢?那就是列出 JDK 的 SPI 缺点

之后再说在 Dubbo 中的针对它的哪些需求做了哪些的改进

这些 JDK 的 SPI 缺点、Dubbo SPI 优点,网上一查一大堆,这里我也给列一下:

  • JDK SPI 的缺点:

JDK 的 SPI 机制在查找实现类的时候,由于配置文件根根据接口的全限定类名命名的,需要先遍历 META-INF/services/ 目录下的所有配置文件,找到对应的配置文件,再将配置文件中的全部实现类都取出来,进行实例化操作

因此呢,它的缺点就是无法按需加载实现类,导致出现资源浪费,并且指定了配置目录 META-INF/services/ ,不是很灵活

  • Dubbo SPI 的优点:

Dubbo 的 SPI 对配置文件的目录规定了多个,各自的职责不同:

  • META-INF/services/ 目录:该目录下的 SPI 配置文件是为了用来兼容 Java SPI 。
  • META-INF/dubbo/ 目录:该目录存放用户自定义的 SPI 配置文件。
  • META-INF/dubbo/internal/ 目录:该目录存放 Dubbo 内部使用的 SPI 配置文件。

Dubbo 的 SPI 代码中还实现了 IOC 和 AOP,可以对扩展的实现类进行依赖注入,以及 AOP 拦截,也就是方法增强

并且 Dubbo 中的 SPI 是通过 K-V 方式配置的,因此可以 按需加载实现类 ,优化了 JDK SPI 的缺点

从这几个点呢,可以看出 Dubbo 的 SPI 机制是非常灵活的,可以针对实现类做出拦截扩展操作,并且性能也不错,按需加载,不会出现资源浪费

Dubbo 中 SPI 使用

先说一下 Dubbo 中的 SPI 使用:

  • 第一步:配置文件如下(配置文件在 META-INF/dubbo 目录下,Dubbo 会自动去扫描该目录中的配置文件):
userServiceImpl1 = com.example.hello.impl.UserServiceImpl1
userServiceImpl2 = com.example.hello.impl.UserServiceImpl2
  • 第二步:SPI 接口:
@SPI
public interface UserService {
   
    void sayHello();
}
  • 第三步:加载实现类
public class DubboSPITest {
   
   @Test
   public void sayHello() throws Exception {
   
       ExtensionLoader<Robot> extensionLoader =
           ExtensionLoader.getExtensionLoader(UserService.class);
       UserService userServiceImpl1 = extensionLoader.getExtension("userServiceImpl1");
       userServiceImpl1.sayHello();
       UserService userServiceImpl2 = extensionLoader.getExtension("userServiceImpl2");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

11来了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值