1. 程式人生 > >SPI(service provider interface 服務提供者介面)

SPI(service provider interface 服務提供者介面)

零. 簡介 SPI 是 JDK 1.5 後提供的一種服務擴充套件介面。目前有不少框架用它來做服務的擴充套件,如 Dubbo。 服務通常指介面(下述例子的 Hello 介面)或者抽象類,服務提供方(下述例子的CHello、JavaHello 類)就是對這個介面或者抽象類的實現,然後按spi標準存放到資源路徑META-INF/services目錄下,檔案的命名(下述例子的  com.wenniuwuren.spi.Hello)為該介面的全限定名,檔案內容每一行寫一個服務實現類,# 號後面為註釋,該檔案只能是 UTF-8 編碼。再按 SPI 規範打包成 jar,再放到 classpath,沒有一點程式碼的侵入性
本質上和我們通常的開發方式一樣,定義介面,子類實現父類,那很多人有疑問,為什麼要開發這麼一套規範? 這種方式主要是針對不同的服務提供方(外掛開發、功能擴充套件等),對不同場景的提供不同的解決方案制定的一套標準,舉個例子,如現在的 JDK 中支援資料庫連線池,如果只支援某個連線池如 Druid,如果其他公司不想用這個 Druid 連線池,如果沒有提供  SPI 擴充套件,那就只有修改 Java 的原始碼,那就有個問題,要升級 JDK 就得再改一次程式碼,而有了 SPI 標準,JDK 只需要提供一個連線池介面,在實現連線池的功能上通過 ServiceLoad 的方式載入服務,那麼第三方只需要實現這個連線池介面,就可以提供不同的服務。
一. 程式碼示例

Maven 專案結構:


SPI 服務介面:

package com.wenniuwuren.spi;

/**
 * Created by hzzhuyibin on 2017/2/14.
 */
public interface Hello {

    void sayHello();
}

SPI 服務提供方:
package com.wenniuwuren.spi.impl;

import com.wenniuwuren.spi.Hello;

/**
 * Created by hzzhuyibin on 2017/2/14.
 */
public class JavaHello implements Hello{
@Override
 public void sayHello() {
System.out.println("Java Hello");
 }
}


package com.wenniuwuren.spi.impl;

import com.wenniuwuren.spi.Hello;

/**
 * Created by hzzhuyibin on 2017/2/14.
 */
public class CHello implements Hello{
@Override
 public void sayHello() {
System.out.println("C Hello");
 }
}


配置檔案 META-INF/services/com.wenniuwuren.spi.Hello:

com.wenniuwuren.spi.impl.CHello # C Hello
com.wenniuwuren.spi.impl.JavaHello # Java Hello

pom.xml 打包示例配置:


參考資料: