切换语言为:繁体
SPI跟API对比着了解更容易懂!

SPI跟API对比着了解更容易懂!

  • 爱糖宝
  • 2024-08-25
  • 2050
  • 0
  • 0

前言

在讨论什么是SPI前,先回忆一下什么是API

  • 什么是API?

实现方提供了接口和实现,我们可以通过调用实现方的接口从而拥有实现方给我们提供的能力,这就是 API

这种情况下,接口和实现都是放在实现方的包中。调用方通过接口调用实现方的功能,而不需要关心具体的实现细节。

SPI跟API对比着了解更容易懂!

什么是SPI?

当接口存在于调用方这边时,这就是**SPI **。由接口调用方确定接口规则,由不同的厂商根据这个规则对接口进行实现,从而提供服务。

SPI跟API对比着了解更容易懂!

举个例子:

  • API:我是一个老板,我需要达到一个目标,然后我去找能帮我达到这个目标的实现方(多个),至于怎么实现的,我不管,我只看结果,也就是说接口和接口实现都由实现方来制定

  • SPI:我是一个老板,我需要达到一个目标,然后我去找能帮我达到这个目标的实现方,我制定一个实现标准,多个实现方根据老板

    提供的实现标准去实现,也就是说接口是由老板(调用方)制定,而接口实现由实现方来制定

JDBC中的SPI

在 JDBC 使用过程中,有注册驱动这一步骤,代码如下:

 Class.forName("com.mysql.jdbc.Driver");

现在,我们将那个案例中的这行代码给注释/删除掉。即 getConnection() 方法代码如下:

public static Connection getConnection() {
    Connection conn = null;
    //try {
        //Class.forName("com.mysql.jdbc.Driver");
        try {
            conn = DriverManager.getConnection(JDBC_URL, USERNAME, PASSWORD);
            System.out.println(conn);
        } catch (SQLException e) {
            System.out.println("数据库连接失败");
        }
    //} catch (ClassNotFoundException e) {
        //System.out.println("驱动包不存在");
    //}
    return conn;
}

会发现,Connection还是能够获取成功的,那为什么 JDBC 中不注册驱动还能连接数据库成功?就是SPI机制的作用了

看一下DriverManger的源代码

public class DriverManager {
    private DriverManager(){}
    static {
        loadInitialDrivers();
        println("JDBC DriverManager initialized");
    }
    ...
}

在loadInitialDrivers()方法中:

会去查找 Driver 接口的服务类,文件路径是:META-INF/services/java.sql.Driver。创建文件里面的实现类

打开IDEA验证一下,去 External Libraries 找到我们的数据库依赖查看,确实如此

SPI跟API对比着了解更容易懂!

SPI机制简化了应用程序的代码,并提高了灵活性和可扩展性

通过SPI机制,不同的数据库供应商可以提供自己的驱动程序,而应用程序可以轻松地与这些不同的数据库进行交互。

Dubbo中的SPI

根据上面的案例,SPI的运行机制已经清楚了,再来看一下Dubbo中哪里用到了SPI

Dubbo SPI 逻辑封装在 ExtensionLoader 类,通过 ExtensionLoader,可加载指定实现类。

Dubbo SPI 所需配置文件需放置在 META-INF/dubbo 这个路径下,同样打开IDEA验证一下

SPI跟API对比着了解更容易懂!

举个例子,项目中需要配置不同的序列化器,由你自己(实现方)去实现由Dubbo(调用方)制定出来的接口

SPI跟API对比着了解更容易懂!

0条评论

您的电子邮件等信息不会被公开,以下所有项均必填

OK! You can skip this field.