切換語言為:簡體
SPI跟API對比著瞭解更容易懂!

SPI跟API對比著瞭解更容易懂!

  • 爱糖宝
  • 2024-08-25
  • 2051
  • 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.