SPI與API

  • 蘇格團隊
  • 做者:Handsome

SPI與API

SPI與咱們熟知的API名字上有點類似,SPI被稱爲服務提供接口,API稱爲應用程序接口,二者的區別大體能夠這樣來對比。 假設有客戶方和服務方,彼此經過約定的接口對接。java

  1. 服務方暴露本身的業務供客戶方調用,則爲提供API服務。
  2. 客戶方實現服務方提供的接口,而後讓服務方去調用本身,則爲提供SPI服務。

咱們平時最多見的SPI服務就是JDBC。經過統一的JDBC規範,客戶方能夠本身實現各類數據源。試想一下,假設開發者想將數據源從Mysql切換到Oracle,若是沒有使用JDBC,切換的過程就須要耗費巨大的人力成本。mysql

如何解決上述的數據源切換問題,這裏須要說一下依賴倒置原則。git

  1. 高層模塊不該該依賴低層模塊,二者都應該依賴抽象
  2. 抽象不該該依賴細節
  3. 細節應該依賴抽象

JDBC鏈接Mysqlgithub

Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(
              "jdbc:mysql://localhost:3306/test", "root", "123456");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from Users");
複製代碼

下面本身實現一個簡易版的JDBC程序。 驅動管理程序,負責加載各SPI服務,用一個Map保存全部加載過的驅動程序,key爲SPI服務自定義的名稱。在調用connection時,只要url中的前綴爲驅動名,則使用該驅動建立鏈接。sql

/** * 驅動管理,負責加載各客戶方提供的數據源服務/ */
public class MyDriverManager {
   /** * 全部註冊的數據源鏈接服務/ */
private static final Map<String, MyDriver> registerDriver = new HashMap<String, MyDriver>();

    public static void registerDriver(String name, MyDriver driver) {
        registerDriver.put(name, driver);
    }

    public static MyConnection getConnection(String url) {
        for (String key : registerDriver.keySet()) {
            if (url.startsWith(key)) {
                return registerDriver.get(key).getConnection(url);
            }
        }
        throw new RuntimeException("no such provider");
    }
}

複製代碼

定義驅動接口bash

public interface MyDriver {
		/** * 獲取鏈接 */
		MyConnection getConnection(String url);
}
複製代碼

客戶方本身實現的驅動程序,靜態代碼塊中執行註冊服務,將驅動註冊到驅動管理程序中。ide

public class MysqlDriver implements MyDriver {

    static {
        MyDriverManager.registerDriver(「mysql」, new MysqlDriver());
    }

    public MyConnection getConnection(String url) {
        System.out.println(「connect to mysql: url = 「 + url);
        return new MysqlConnection();
    }
}
複製代碼

實際執行時,要先使用Class.forName加載一下驅動程序,不然static代碼塊不會執行,沒法將驅動加載到驅動管理程序中。url

public class Main {

    public static void main(String[] args) throws ClassNotFoundException {
        		 Class.forName(「com.github.yaolang.chapter01.spi1.MysqlDriver」);
        MyConnection myConnection = MyDriverManager.getConnection(「mysql://localhost:8080」);
        System.out.println(myConnection);
    }
}
複製代碼

如下爲輸出結果spa

connect to mysql: url = mysql://localhost:8080
com.github.yaolang.chapter01.spi1.MysqlConnection@60e53b93
複製代碼
相關文章
相關標籤/搜索