您好,登錄后才能下訂單哦!
SPI是Service Provider Interface的簡稱,是JDK默認提供的一種將接口和實現類進行分離的機制。這種機制能將接口和實現進行解耦,大大提升系統的可擴展性。
SPI機制約定:當一個Jar包需要提供一個接口的實現類時,這個Jar包需要在META-INF/services/目錄里同時創建一個以服務接口命名的文件。該文件里就是實現該服務接口的具體實現類。而當外部程序裝配這個模塊的時候,就能通過該Jar包META-INF/services/里的配置文件找到具體的實現類名,并裝載實例化,完成模塊的注入。
比如下面的列子,
jcl-over-slf4j
這個Jar包提供了conmon-logging中
LogFactory
這個接口的實現。
文件中的內容如下:
JDK為了方便查找 服務的實現,還提供了一個工具類:java.util.ServiceLoader。
上面代碼中使用
ServiceLoader
遍歷使用SPI機制提供的所有
LogFactory
實現。
SPI機制的主要應用有框架擴展和組件的替換等,比如
下面就一步步從定義接口到提供SPI實現類來演示下SPI機制具體的使用方式。
step1:先定義一個接口
<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; word-wrap: break-word; position: relative !important;">
Copy
`public interface SaySomething {
String say(String name);
}`</pre>
step2:編寫實現類
<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; word-wrap: break-word; position: relative !important;">
Copy
public class ASaySomething implements SaySomething { @Override public String say(String name) { return "Hi,"+name+", l am A..."; } }
</pre>
step3:在resource下添加META-INFO/services目錄
添加完這個目錄后,添加一個以
SaySomething
接口的全限定名為名字的文件,這個文件的內容是你要設置的具體實現類。這邊我們就設置實現類為上面的
ASaySomething
。
step4:使用SPI機制
<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; word-wrap: break-word; position: relative !important;">
Copy
public static void main(String[] args) { ServiceLoader<SaySomething> loader = ServiceLoader.load(SaySomething.class); loader.forEach(item ->{item.say("csx");}); }
</pre>
在開發中我們還經常會提到API這個名詞,下面也總結下兩者的區別:
API (Application Programming Interface)在大多數情況下,都是實現方制定接口并完成對接口的實現,調用方僅僅依賴接口調用,且無權選擇不同實現。 從使用人員上來說,API 直接被應用開發人員使用。
SPI (Service Provider Interface)是調用方來制定接口規范,提供給外部來實現,調用方在調用時則選擇自己需要的外部實現。 從使用人員上來說,SPI 被框架擴展人員使用。
優點
缺點
ServiceLoader
并不是線程安全的。免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。