中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

作為一個Java工程師,你應該要知道SPI機制

發布時間:2020-08-14 03:17:45 來源:ITPUB博客 閱讀:110 作者:慕容扶蘇 欄目:編程語言

什么是 SPI

SPI是Service Provider Interface的簡稱,是JDK默認提供的一種將接口和實現類進行分離的機制。這種機制能將接口和實現進行解耦,大大提升系統的可擴展性。

SPI機制約定:當一個Jar包需要提供一個接口的實現類時,這個Jar包需要在META-INF/services/目錄里同時創建一個以服務接口命名的文件。該文件里就是實現該服務接口的具體實現類。而當外部程序裝配這個模塊的時候,就能通過該Jar包META-INF/services/里的配置文件找到具體的實現類名,并裝載實例化,完成模塊的注入。

比如下面的列子, jcl-over-slf4j這個Jar包提供了conmon-logging中 LogFactory這個接口的實現。

作為一個Java工程師,你應該要知道SPI機制
image

文件中的內容如下:

作為一個Java工程師,你應該要知道SPI機制

JDK為了方便查找 服務的實現,還提供了一個工具類:java.util.ServiceLoader。

作為一個Java工程師,你應該要知道SPI機制

上面代碼中使用 ServiceLoader遍歷使用SPI機制提供的所有 LogFactory實現。

應用場景

SPI機制的主要應用有框架擴展和組件的替換等,比如

  • JDBC接口實現類的運行時加載:我們連接具體的數據庫是都需要添加相關的Jar包依賴,但是不需要我們再做任何其他配置,只要將Jar包放到classpath下就行了。這是一個最常見的SPI應用場景。
  • 日志門面加載具體的日志實現類:之前的博客中介紹到,jcl和slf4j等只是日志實現類,Log4j和LOgBack才是具體的日志實現。JCL和SLF4J加載日志實現類時也使用了SPI機制,具體請看上面章節中舉的列子。
  • Spring中大量使用了SPI:比如對servlet3.0規范對ServletContainerInitializer的實現、自動類型轉換Type Conversion SPI(Converter SPI、Formatter 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和SPI的比較

在開發中我們還經常會提到API這個名詞,下面也總結下兩者的區別:

  • API (Application Programming Interface)在大多數情況下,都是實現方制定接口并完成對接口的實現,調用方僅僅依賴接口調用,且無權選擇不同實現。 從使用人員上來說,API 直接被應用開發人員使用。

  • SPI (Service Provider Interface)是調用方來制定接口規范,提供給外部來實現,調用方在調用時則選擇自己需要的外部實現。 從使用人員上來說,SPI 被框架擴展人員使用。

優缺點

優點

  • 使用Java SPI機制的優勢是實現解耦,使得第三方服務模塊的裝配控制的邏輯與調用者的業務代碼分離,而不是耦合在一起。應用程序可以根據實際業務情況啟用框架擴展或替換框架組件

缺點

  • SPI必須先將接口的所有實現類都遍歷出來才能最后選擇具體使用哪個類。有些不要的類也會被實例化,可能會比較浪費內存。
  • ServiceLoader并不是線程安全的。
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

平利县| 太和县| 宜昌市| 玉山县| 阿巴嘎旗| 肥城市| 阳信县| 湖州市| 仙游县| 新巴尔虎左旗| 南京市| 关岭| 宾阳县| 方正县| 普格县| 桐乡市| 临漳县| 小金县| 泾川县| 二连浩特市| 土默特左旗| 建水县| 廊坊市| 珲春市| 泸定县| 桐梓县| 抚宁县| 承德县| 霸州市| 育儿| 白河县| 宜君县| 岳池县| 富民县| 永川市| 登封市| 永康市| 蒙自县| 定陶县| 武川县| 英德市|