最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文搞懂Java SPI機制的原理與使用

 更新時間:2022年10月09日 09:14:12   作者:鴨血粉絲Tang  
Java 程序員在日常工作中經常會聽到 SPI,而且很多框架都使用了 SPI 的技術,那么問題來了,到底什么是 SPI 呢?今天小編就帶大家好好了解一下 SPI

Java 程序員在日常工作中經常會聽到 SPI,而且很多框架都使用了 SPI 的技術,那么問題來了,到底什么是 SPI 呢?今天阿粉就帶大家好好了解一下 SPI。

SPI 概念

SPI 全稱是 Service Provider Interface,是一種 JDK 內置的動態(tài)加載實現(xiàn)擴展點的機制,通過 SPI 技術我們可以動態(tài)獲取接口的實現(xiàn)類,不用自己來創(chuàng)建。

這里提到了接口和實現(xiàn)類,那么 SPI 技術上具體有哪些技術細節(jié)呢?

  • 接口:需要有一個功能接口;
  • 實現(xiàn)類:接口只是規(guī)范,具體的執(zhí)行需要有實現(xiàn)類才行,所以不可缺少的需要有實現(xiàn)類;
  • 配置文件:要實現(xiàn) SPI 機制,必須有一個與接口同名的文件存放于類路徑下面的  META-INF/services 文件夾中,并且文件中的每一行的內容都是一個實現(xiàn)類的全路徑;
  • 類加載器 ServiceLoaderJDK 內置的一個類加載器,用于加載配置文件中的實現(xiàn)類;

舉個栗子

上面說了 SPI 的幾個概念,接下來阿粉就通過一個栗子來帶大家感受一下具體的用法。

第一步

創(chuàng)建一個接口,這里我們創(chuàng)建一個解壓縮的接口,其中定義了壓縮和解壓的兩個方法。

package?com.example.demo.spi;

/**
?*?<br>
?*?<b>Function:</b><br>
?*?<b>Author:</b>@author?ziyou<br>
?*?<b>Date:</b>2022-10-08 21:31<br>
?*?<b>Desc:</b>無<br>
?*/
public?interface?Compresser?{
??byte[]?compress(byte[]?bytes);
??byte[]?decompress(byte[]?bytes);
}

第二步

再寫兩個對應的實現(xiàn)類,分別是 GzipCompresser.java 和 WinRarCompresser.java 代碼如下

package?com.example.demo.spi.impl;

import?com.example.demo.spi.Compresser;

import?java.nio.charset.StandardCharsets;

/**
?*?<br>
?*?<b>Function:</b><br>
?*?<b>Author:</b>@author?ziyou<br>
?*?<b>Date:</b>2022-10-08 21:33<br>
?*?<b>Desc:</b>無<br>
?*/
public?class?GzipCompresser?implements?Compresser?{
??@Override
??public?byte[]?compress(byte[]?bytes)?{
????return"compress?by?Gzip".getBytes(StandardCharsets.UTF_8);
??}
??@Override
??public?byte[]?decompress(byte[]?bytes)?{
????return?"decompress?by?Gzip".getBytes(StandardCharsets.UTF_8);
??}
}
package?com.example.demo.spi.impl;

import?com.example.demo.spi.Compresser;

import?java.nio.charset.StandardCharsets;

/**
?*?

?*?<b>Function:</b>

?*?<b>Author:</b>@author?ziyou

?*?<b>Date:</b>2022-10-08 21:33

?*?<b>Desc:</b>無

?*/
public?class?WinRarCompresser?implements?Compresser?{
??@Override
??public?byte[]?compress(byte[]?bytes)?{
????return?"compress?by?WinRar".getBytes(StandardCharsets.UTF_8);
??}

??@Override
??public?byte[]?decompress(byte[]?bytes)?{
????return?"decompress?by?WinRar".getBytes(StandardCharsets.UTF_8);
??}
}

第三步

創(chuàng)建配置文件,我們接著在 resources 目錄下創(chuàng)建一個名為 META-INF/services 的文件夾,在其中創(chuàng)建一個名為 com.example.demo.spi.Compresser 的文件,其中的內容如下:

com.example.demo.spi.impl.WinRarCompresser
com.example.demo.spi.impl.GzipCompresser

注意該文件的名稱必須是接口的全路徑,文件里面的內容每一行都是一個實現(xiàn)類的全路徑,多個實現(xiàn)類就寫在多行里面,效果如下。

第四步

有了上面的接口,實現(xiàn)類和配置文件,接下來我們就可以使用 ServiceLoader 動態(tài)加載實現(xiàn)類,來實現(xiàn) SPI 技術了,如下所示:

package?com.example.demo;

import?com.example.demo.spi.Compresser;

import?java.nio.charset.StandardCharsets;
import?java.util.ServiceLoader;

public?class?TestSPI?{
??public?static?void?main(String[]?args)?{
????ServiceLoader<Compresser>?compressers?=?ServiceLoader.load(Compresser.class);
????for?(Compresser?compresser?:?compressers)?{
??????System.out.println(compresser.getClass());
????}
??}
}

運行的結果如下

可以看到我們正常的獲取到了接口的實現(xiàn)類,并且可以直接使用實現(xiàn)類的解壓縮方法。

原理

知道了如何使用 SPI 接下來我們來研究一下是如何實現(xiàn)的,通過上面的測試我們可以看到,核心的邏輯是 ServiceLoader.load() 方法,這個方法有點類似于 Spring 中的根據(jù)接口獲取所有實現(xiàn)類一樣。

點開 ServiceLoader 我們可以看到有一個常量 PREFIX,如下所示,這也是為什么我們必須在這個路徑下面創(chuàng)建配置文件,因為 JDK 代碼里面會從這個路徑里面去讀取我們的文件。

同時又因為在讀取文件的時候使用了 class 的路徑名稱,因為我們使用 load 方法的時候只會傳遞一個 class,所以我們的文件名也必須是接口的全路徑。

通過 load 方法我們可以看到底層構造了一個 java.util.ServiceLoader.LazyIterator 迭代器。

在迭代器中的 parse 方法中,就獲取了配置文件中的實現(xiàn)類名稱集合,然后在通過反射創(chuàng)建出具體的實現(xiàn)類對象存放到 LinkedHashMap<String,S> providers = new LinkedHashMap<>(); 中。

常用的框架

SPI 技術的使用非常廣泛,比如在 Dubble,不過 Dubble 中的 SPI 有經過改造的,還有我們很常見的數(shù)據(jù)庫的驅動中也使用了 SPI,感興趣的小伙伴可以去翻翻看,還有 SLF4J 用來加載不同提供商的日志實現(xiàn)類以及 Spring 框架等。

優(yōu)缺點

前面介紹了 SPI 的原理和使用,那 SPI 有什么優(yōu)缺點呢?

優(yōu)點

優(yōu)點當然是解耦,服務方只要定義好接口規(guī)范就好了,具體的實現(xiàn)可以由不同的 Jar 進行實現(xiàn),只要按照規(guī)范實現(xiàn)功能就可以被直接拿來使用,在某些場合會被進行熱插拔使用,實現(xiàn)了解耦的功能。

缺點

一個很明顯的缺點那就是做不到按需加載,通過源碼我們看到了是會將所有的實現(xiàn)類都進行創(chuàng)建的,這種做法會降低性能,如果某些實現(xiàn)類實現(xiàn)很耗時了話將影響加載時間。同時實現(xiàn)類的命名也沒有規(guī)范,讓使用者不方便引用。

到此這篇關于一文搞懂Java SPI機制的原理與使用的文章就介紹到這了,更多相關Java SPI機制內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論

二手房| 麻栗坡县| 方正县| 永顺县| 武隆县| 大石桥市| 台中县| 剑河县| 安泽县| 铅山县| 天全县| 扶风县| 连城县| 古丈县| 神木县| 延吉市| 满洲里市| 平远县| 博罗县| 衢州市| 余干县| 五家渠市| 湄潭县| 阳东县| 同德县| 萝北县| 嘉义市| 宜兰县| 独山县| 当阳市| 河津市| 安康市| 镇远县| 霍邱县| 讷河市| 通州区| 嘉鱼县| 威宁| 精河县| 上高县| 扎兰屯市|