API:API(Application Programming Interface)表示應用程序編程接口
SPI:SPI(Service Provider Interface)表示服務提供商接口API與SPI的關系
框架提供API及其實現,框架在實現過程中提供SPI回調機制。SPI是框架的擴展點。如果使用框架方要擴展框架,可以自己實現SPI並注入框架,於是框架使用方其實也是一個服務提供商。
SPI實現有兩種方式,一種是第三方提供實現,另一種是應用自身自己提供實現
看一下API/SPI關系圖1,第三方提供商實現了SPI,應用引入第三方提供商的第三方庫

舉例
java中JDBC是一個編程接口,而Driver是一個SPI,同時不同數據庫廠商會提供Driver的實現。應用中要使用JDBC編程接口時需要引入第三方數據庫廠商驅動包,第三方廠商提供的驅動包其實就是SPI的實現。
框架如何發現SPI?框架可以使用java提供的java.util.ServiceLoader類得到SPI的實現。
如ServiceLoader<PullToolFactory> pullToolFactorys = ServiceLoader.load(PullToolFactory.class);
應用或第三方提供商如何注入SPI實現?
應用或第三方包在jar包的META-INF/services/目錄里同時創建一個以服務接口命名的文件。該文件里就是實現該服務接口的具體實現類的完全限定名。而當框架調用ServiceLoader.load(PullToolFactory.class),就能通過該jar包META-INF/services/里的配置文件找到具體的實現類名,並裝載實例化,完成SPI實現的注入。
總結:
可以想象,使用SPI設計,框架可以很容易引入擴展點,同時應用要擴展框架邏輯也很容易實現。框架可擴展設計可以基於這個原則進行設計擴展點。
SPI設計的關鍵是程序定義通用的接口比如JDBC,然后不同服務提供商根據接口做自己的實現如Driver,然后程序在運行時根據加載到的接口實現不同,實現不同具體的功能,如操作不同的數據庫。