精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

從實現到原理,聊聊Java中的SPI動態擴展

開發 前端
我們今天暫且不提spring的SPI擴展,先來看看java本身自帶的SPI擴展機制是怎么一回事。

八股文背多了,相信大家都聽說過一個詞,SPI擴展。

有的面試官就很喜歡問這個問題,SpringBoot的自動裝配是如何實現的?

基本上,你一說是基于spring的SPI擴展機制,再把spring.factories文件和EnableAutoConfiguration提一下,那么這個問題就答的八九不離十了。

就像四五年前,我去面試的時候被問到這個問題,SPI動態擴展機制這幾個詞從嘴里一說出來,就把面試官唬的一愣一愣的。可能他們也沒見過這么能裝逼的,一句話能簡簡單單說明白,非要拽一個聽上去很高大上的詞。

話說回來,被唬住的可不止是面試官,其實還有我自己。至于SPI擴展究竟是個啥,是怎么實現的,我當時也根本不明白。

不過現在的面試就是這樣,對線八股文,要想唬住面試官,就得先唬住自己。

那么我們今天暫且不提spring的SPI擴展,先來看看java本身自帶的SPI擴展機制是怎么一回事。

1、簡介

SPI的全稱是Service Provider Interface,翻譯過來就是服務提供者的接口,它所實現的其實是一種服務的發現機制。

這么說起來可能還是有點不好理解,我舉個例子來類比一下。

在spring項目中,寫service層代碼前,會約定俗成的會添加一個接口層。然后通過spring中的依賴注入,可以借助@Autowired等方式注入這個接口的實現類的實例對象,之后對于service的調用一般也基于接口操作。

簡單形容就是這樣的:

圖片

如圖所示,接口、實現類都是由服務提供方提供,我們可以把controller看作服務調用者,調用方只管調用接口就可以了。

雖然也有聲音認為,大部分情況下service只有一個實現類,接口層顯得有些多余。但是在《Head First Design Patterns》這本書中,大佬們還是建議過:

Program to an interface, not an implementation.

沒錯,就是常說的要面向接口編程。至于好處,也不外乎是降低耦合度、方便日后擴展、提高了代碼的靈活性和可維護性等等。

在上面這個例子里,這個接口層和其中的方法我們可以稱之為API,而我們要討論的SPI和它相比,有類似也有差異,還是先看圖:

圖片

簡單來說,就是服務的調用方定義一個接口規范,可以由不同的服務提供者實現。并且,調用方能夠通過某種機制來發現服務提供方,并通過接口調用它的能力。

通過對比,我們可以看出它們雖然都有著接口這一層面,但還是有很大的不同:

API中的接口是服務提供者給服務調用者的一個功能列表,而SPI中更多強調的是,服務調用者對服務實現的一種約束,服務提供者根據這種約束實現的服務,可以被服務調用者發現。

說白了,Java中的SPI實現的就是,你按我的接口規范實現服務,我就能通過某種機制為這個接口尋找到這個服務。

這么說起來可能還有些抽象,下面我們舉一個例子,類比具體描述一下這個過程。

2、定義接口

說起智能家居系統,大家現在都比較熟悉了,只要是相同品牌下的產品,連上wifi就能夠通過手機app控制了,非常方便。

雖然產品不斷更新換代,型號更新層出不窮,但是同種家電在app上操作起來,功能一般都是一樣的。就拿空調來說,我們在app上操作起來一般也就三個主要功能:開關,選模式,調節溫度。

假設我現在在客廳、臥室、書房安裝了3款不同型號的空調,并把它們都接入到了我app中,那么之后的操作都是相同的幾個按鍵,簡單粗暴。

圖片

思考一下,無論是開關還是調溫,都是通過app去調用設備的接口罷了,那么如果不同型號的空調各寫各的接口,后端app在開發的時候光對接接口都麻煩的要死。

解決方法也很簡單,我先定義一套接口規范,不管你以后什么型號的空調,都按我的規范來實現接口。以后只要我能發現你的設備,那么都可以按相同的方法來調用接口。

那么下面就先來定義這么一套接口規范,如果你以后想要接入智能家居系統,那么就要遵循這個規范來開發接口。

新建一個項目作為標準,就叫aircondition-standard好了,然后創建一個接口。除了3個操作以外,我們再添加一個獲取空調型號的方法。

public interface IAircondition {
// 獲取型號
String getType();

// 開關
void turnOnOff();

// 調節溫度
void adjustTemperature(int temperature);

// 模式變更
void changeModel(int modelId);
}

這個接口后面要給服務的實現方來使用,用maven把它打成jar包:

mvn clean install

之后服務提供者在項目中就可以引入這個jar包了,有了這套規范,就保證了產品后期不管怎么更新換代,都能接入到系統來。

3、服務實現

制定并發布完規則后,掛式空調作為第一個服務提供者就來了,新建一個項目aircondition-hanging-type,并引入剛才打好的jar包:

<dependency>
<groupId>com.cn.hydra</groupId>
<artifactId>aircondition-standard</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

創建服務類,并實現前面定義的接口:

public class HangingTypeAircondition
implements IAircondition{
public String getType() {
return "HangingType";
}

public void turnOnOff() {
System.out.println("掛式空調開關");
}

public void adjustTemperature(int i) {
System.out.println("掛式空調調節溫度");
}

public void changeModel(int i) {
System.out.println("掛式空調更換模式");
}
}

在項目的resources的目錄下,創建META-INF/services目錄,然后以前面定義的接口名com.cn.hydra.IAircondition創建文件,并在文件中寫入實現類的全限定名。

com.cn.hydra.HangingTypeAircondition

整個項目結構非常簡單:

圖片

這樣,一個服務方的簡單實現就搞定了,用maven打成jar包,之后就可以提供給調用方使用了。

同理,我們可以再創建一個立式空調的項目aircondition-vertical-type,也只創建一個服務類:

public class VerticalTypeAircondition
implements IAircondition{
public String getType() {
return "VerticalType";
}

public void turnOnOff() {
System.out.println("立式空調開關");
}

public void adjustTemperature(int i) {
System.out.println("立式空調調節溫度");
}

public void changeModel(int i) {
System.out.println("立式空調更換模式");
}
}

還是按上面的命名規則,創建一個配置文件:

com.cn.hydra.VerticalTypeAircondition

同樣,打成jar包就完事了,至于服務調用者如何去發現和調用這兩個服務,下面詳細再說。

4、服務發現

現在兩個服務提供方都實現了接口,下面關鍵的一步就是服務發現,這一步java中的spi發現機制已經幫我們實現好了。

創建一個新項目aircondition-app,引入上面打好的兩個jar包。

<dependencies>
<dependency>
<groupId>com.cn.hydra</groupId>
<artifactId>aircondition-hanging-type</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>com.cn.hydra</groupId>
<artifactId>aircondition-vertical-type</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>

按照上面的說法,雖然每個服務提供者對于接口都有不同的實現,但是作為調用者來說,它并不需要關心具體的實現類,我們要做的是通過接口來調用服務提供者實現的方法。

下面,就是關鍵的服務發現環節,我們寫一個方法,根據型號去調用對應空調的開關方法。

public class AirconditionApp {
public static void main(String[] args) {
new AirconditionApp().turnOn("VerticalType");
}

public void turnOn(String type){
ServiceLoader<IAircondition> load = ServiceLoader
.load(IAircondition.class);

for (IAircondition iAircondition : load) {
System.out.println("檢測到:"+iAircondition.getClass().getSimpleName());
if (type.equals(iAircondition.getType())){
iAircondition.turnOnOff();
}
}
}
}

測試結果:

圖片

可以看到,測試過程中,通過定義的接口IAircondition發現了兩個實現類,并通過參數,調用了特定實現類的某個方法。整段代碼中沒有出現過具體的服務實現類,操作都是通過接口調用。

5、原理

了解了spi的工作流程,我們再來看看它的實現,其實最關鍵的就是上面代碼中出現的ServiceLoader這個類。

上面的示例代碼中,對于ServiceLoader的load()方法的結果,我們用for循環進行了遍歷,這一點我們看一下源碼就能明白,因為ServiceLoader實現了Iterable這一接口,而整個服務發現的核心,就在它的iterator()方法中。

圖片

注意這里面有兩個關鍵的東西,找一下在源碼中定義的地方:

圖片

注釋寫的非常明白,providers就是一個緩存,在迭代器中如果先從這里面進行查找,如果里面有就繼續往下找,沒有了的話就用這個懶加載的lookupIterator查找。

那么就簡單了,接著往下看LazyIterator,看看它里面的hasNext()和next()兩個方法是怎么實現的。

圖片

這個acc是一個安全管理器,在前面通過System.getSecurityManager()判斷并賦值,debug看一下這里都是null,所以直接看hasNextService()和nextService()方法就可以了。

在hasNextService()方法中,會取出接口取出實現類的類名放到nextName中:

圖片

接下來,在nextService()方法中,則會先加載這個實現類,然后實例化對象,最終放入緩存中去。

圖片

在迭代器的迭代過程中,會完成所有實現類的實例化,其實歸根結底,還是基于java反射去實現的。

6、應用

要說spi的實際應用,大家最常見的應該就是日志框架slf4j了,它利用spi實現了插槽式接入其他具體的日志框架。

說白了,slf4j本身就是個日志門面,并不提供具體的實現,需要綁定其他具體實現才能真正的引入日志功能。

例如我們可使用log4j2作為具體的綁定器,只需要在pom中引入slf4j-log4j12,就可以使用具體功能。

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>2.0.3</version>
</dependency>

引入項目后,點開它的jar包看一下具體結構:

圖片

有沒有發現一個彩蛋,先說為什么我們pom中引入的明明是slf4j-log4j12,實際上引入的是slf4j-reload4j?翻一下官網的文檔:

圖片

大意就是在2015年和2022年,log4j1.x就已經宣布end of life終止了,原因也不難猜,估計是因為頻繁爆出的漏洞。在那之后,slf4j-log4j在構建階段就會自動重定向到slf4j-reload4j了,并且官方也強烈建議使用slf4j-reload4j作為替代。

再回頭看一下jar包的META-INF.services里面,通過spi注入了Reload4jServiceProvider這個實現類,它實現了SLF4JServiceProvider這一接口,在它的初始化方法initialize()中,會完成初始化等工作,后續可以繼續獲取到LoggerFactory和Logger等具體日志對象。

7、總結

Java中的SPI提供了一種比較特別的服務發現和調用機制,通過接口靈活的將服務調用與服務提供者分離,用于提供給第三方實現擴展時還是很方便的。但是也有缺點,比方說一旦加載一個接口,就會把所有實現類都加載進來,可能會加載到不需要的冗余服務。不過站在整體角度上,還是給我們提供了一種非常不錯的框架擴展、集成的思路。

責任編輯:姜華 來源: 碼農參上
相關推薦

2023-02-27 22:03:06

數據庫內存RocketMQ

2025-05-20 05:53:07

DubboSPI機制

2024-12-23 15:05:29

2020-11-20 07:51:02

JavaSPI機制

2021-07-14 14:05:24

Fragment項目結構

2022-05-06 08:26:32

JavaSPI機制

2024-08-05 11:14:45

2025-03-27 02:00:00

SPIJava接口

2024-09-04 10:44:19

2022-07-08 08:37:23

Nacos服務注冊動態配置

2024-10-15 08:37:08

2023-06-05 08:07:33

JavaJava SPI

2025-01-15 15:47:36

2025-03-04 09:02:25

JavaSPI機制

2025-01-07 09:07:36

接口屬性路徑

2024-09-13 16:47:06

模型量化AI

2025-07-18 07:19:00

2020-02-19 19:18:02

緩存查詢速度淘汰算法

2025-05-08 03:25:00

DubboSPI機制

2024-05-09 09:55:08

點贊
收藏

51CTO技術棧公眾號

欧美性生交大片免费| 欧美一区=区| 日韩一区二区三区电影 | jizz在线观看中文| 精品伊人久久久久7777人| 欧美大学生性色视频| 久久精品国产亚洲av麻豆| 成人在线视频免费| 亚洲图片欧美一区| 午夜精品美女久久久久av福利| 国产夫妻自拍av| 免费亚洲婷婷| 九九久久久久99精品| 国产女人18毛片水真多18| 精品欧美一区二区三区在线观看 | 欧美亚洲一二三区| 3d成人动漫在线| 99久久综合狠狠综合久久| 国产精品日韩专区| 国产成人一区二区三区影院在线| 日韩激情在线| 日韩精品在线观看一区二区| 久久综合在线观看| 精品欧美一区二区三区在线观看| 亚洲国产一区二区视频| 椎名由奈jux491在线播放| 久久视频精品在线| 2021狠狠干| 韩国中文字幕2020精品| 成人中文字幕合集| 成人在线精品视频| 亚洲国产成人精品女人久久| 国一区二区在线观看| 最新91在线视频| 亚洲熟妇无码av| 综合激情久久| 欧美一二三区在线观看| 欧美婷婷精品激情| 18video性欧美19sex高清| 成人免费在线播放视频| 日韩欧美视频一区二区三区四区| 日批免费在线观看| 激情都市一区二区| 国产日韩欧美在线播放| 免费一级a毛片| 久久久成人网| 欧美中文字幕在线| 欧美日韩综合在线观看| 欧美日韩中文| 久久久久久91| 久久精品性爱视频| 影音国产精品| 91国内免费在线视频| 天堂资源在线播放| 日韩午夜精品| 91精品国产高清自在线看超| 国产精品久久久免费视频| 99精品99| 日韩免费黄色av| 久久精品视频2| 日本欧美一区二区三区| 国产精品久久久久久中文字| 最新中文字幕第一页| 日本亚洲天堂网| 国产欧美最新羞羞视频在线观看| 一本一道精品欧美中文字幕| 久久爱www久久做| 91久久久亚洲精品| 亚洲a视频在线| 成人深夜在线观看| 久久青青草原| 成人在线视频成人| 成人免费在线观看入口| 老司机激情视频| 三级在线观看视频| 色拍拍在线精品视频8848| 在线免费视频a| 亚洲精品伦理| 日韩精品一区二区在线观看| 久久久老熟女一区二区三区91| 视频福利一区| 日韩少妇与小伙激情| 日韩欧美综合视频| 日韩亚洲在线| 国产精品人成电影在线观看| 国产欧美久久久| 成人高清在线视频| 日本一区二区三区精品视频| 国产盗摄在线观看| 性做久久久久久免费观看| 精品久久久久av| 99久久久国产| 亚洲精品国精品久久99热| 成都免费高清电影| 欧美.www| 日本成人免费在线| 国产视频第一页| 久久综合色婷婷| 法国空姐在线观看免费| 亚洲色图官网| 欧美另类变人与禽xxxxx| 国产精品久久久久久在线观看| 国产一区99| 欧美激情区在线播放| 午夜精品免费观看| 国产成人8x视频一区二区| 欧美韩国日本精品一区二区三区| 国产一二三区在线观看| 一本久道久久综合中文字幕| 国产美女视频免费看| 日韩超碰人人爽人人做人人添| 中文字幕在线观看日韩| 精品美女久久久久| 国产高清视频一区| 亚洲精品一区二区毛豆| 男人天堂视频在线观看| 欧美一区二区黄| 亚洲一二三精品| 翔田千里一区二区| 99久久自偷自偷国产精品不卡| yw视频在线观看| 婷婷综合另类小说色区| 美女又黄又免费的视频| 999精品在线| 国产成人a亚洲精品| 黄色三级网站在线观看| 亚洲视频狠狠干| 亚洲黄色a v| 国产精品探花在线观看| 97国产suv精品一区二区62| 国产乱码精品一区二区| 国产精品沙发午睡系列990531| 免费成人在线视频网站| 国产精东传媒成人av电影| 久久天天躁狠狠躁夜夜av| 中文字幕视频一区二区| 久久亚洲免费视频| 男人靠女人免费视频网站| 国产在线播放精品| 欧美激情精品久久久久久| 国产日韩免费视频| 亚洲精选在线视频| 在线看免费毛片| 天堂美国久久| 91久久精品在线| 国产三区视频在线观看| 91精品国产综合久久精品app| 成人免费视频入口| 麻豆精品视频在线观看视频| 亚洲精品一卡二卡三卡四卡| 成人全视频在线观看在线播放高清 | 欧美国产欧美亚洲国产日韩mv天天看完整| 91一区二区视频| 国产精品家庭影院| 日韩av一卡二卡三卡| 五月天综合网站| 91亚洲精品在线| 日本在线观看大片免费视频| 精品国免费一区二区三区| 国产精品99无码一区二区| 波多野结衣在线一区| 成年人午夜视频在线观看| 欧美黑白配在线| 啪一啪鲁一鲁2019在线视频| 日本一二三区在线视频| 91福利在线观看| 精品女人久久久| 国产在线精品一区二区三区不卡| 欧美日韩中文字幕在线播放| 国产乱人伦丫前精品视频| 欧美一级视频在线观看| 国产www.大片在线| 在线电影院国产精品| 欧美激情一区二区视频| 99久久久久久99| 国产精品无码av无码| 99久久99久久精品国产片桃花| 亚洲一区二区免费在线| free性护士videos欧美| 国产午夜精品视频| www.麻豆av| 欧美午夜性色大片在线观看| 日韩精品电影一区二区三区| 国产成人综合视频| a√天堂在线观看| 色喇叭免费久久综合网| 不卡视频一区二区三区| 亚洲天堂资源| 欧美成人精品一区二区| 污视频软件在线观看| 欧美日韩中字一区| 亚洲精品在线观看av| 欧美国产精品专区| 亚洲成年人在线观看| 青青国产91久久久久久| 中文字幕日韩精品无码内射| 最新亚洲精品| 亚洲综合精品伊人久久| 电影一区二区三| 欧美疯狂做受xxxx高潮| yourporn在线观看视频| 亚洲国产精品大全| 依依成人在线视频| 黄色一区二区在线| 欧美日韩黄色网| 久久久不卡网国产精品二区| 日本wwww色| 免费人成网站在线观看欧美高清| www.日本少妇| 婷婷综合网站| 色一情一乱一伦一区二区三欧美| 波多野结衣欧美| 国产在线观看精品| 亚洲成a人片| 91成人福利在线| 人人澡人人添人人爽一区二区| 在线观看欧美日韩| 四虎精品成人影院观看地址| 日韩欧美在线一区二区三区| 波多野结衣mp4| 欧美视频二区36p| 国产无码精品在线播放| 亚洲视频图片小说| 大吊一区二区三区| 久久欧美一区二区| 在线观看国产网站| 高清在线不卡av| 最好看的中文字幕| 麻豆一区二区99久久久久| 韩国一区二区av| 一本色道久久综合亚洲精品不| 黄网站色视频免费观看| 99tv成人| 亚洲欧洲一二三| 成人写真视频| 日韩资源av在线| 蜜臀av免费一区二区三区| 激情小说综合网| 精品按摩偷拍| 含羞草久久爱69一区| 国内精品免费| 久久久久无码国产精品一区| 精品午夜电影| 久久99精品国产一区二区三区| 国产精品毛片视频| 国产精品手机在线| 狼人精品一区二区三区在线| 国产伦理久久久| 国产成人一二片| 久久精品第九区免费观看| 日韩欧美中文字幕电影| 久久伊人资源站| 欧美禁忌电影网| 日韩一区不卡| 手机在线电影一区| 992tv成人免费观看| 欧美 日韩 国产一区二区在线视频 | 日本大臀精品| 国产一区二区三区久久精品 | 密臀av一区二区三区| 秋霞国产午夜精品免费视频| 国产三级三级看三级| 久久精品国产99| 99国产精品视频免费观看| 白嫩少妇丰满一区二区| 日韩精品亚洲专区| 一道本视频在线观看| 久久99久久久久| 韩国三级丰满少妇高潮| www.亚洲精品| 国产人妻大战黑人20p| 国产精品久久久久久久裸模| 色哟哟一一国产精品| 亚洲免费在线视频一区 二区| 国产在线视频在线观看| 欧美性黄网官网| 中文字幕一区二区在线视频| 91麻豆精品国产自产在线 | 日韩av综合网站| 国产综合视频一区二区三区免费| 中文字幕欧美国内| av色综合久久天堂av色综合在| 久久久久久尹人网香蕉| 天堂在线中文网官网| 国产精品高潮在线| 久久久国产精品入口麻豆| 国产一区二区高清不卡| 成人免费在线播放| 欧美www视频| 尤物视频最新网址| 亚洲欧洲国产日本综合| 久久精品美女视频| 欧美午夜影院一区| 精品国产一级片| 亚洲区一区二区| 自拍亚洲图区| 国产精品大陆在线观看| 99a精品视频在线观看| 日产精品一线二线三线芒果| 欧美韩日精品| 波多结衣在线观看| 99久久精品费精品国产一区二区| 性爱在线免费视频| 五月开心婷婷久久| 国产女人高潮毛片| 亚洲最新av在线网站| 91在线三级| 成人免费高清完整版在线观看| 日韩av午夜| 乱熟女高潮一区二区在线| 日韩av在线发布| 国产婷婷在线观看| 中文字幕一区二区三区在线不卡 | 久久久久久久久久久久| 一区二区三区丝袜| 中文字幕av影视| 日韩高清免费观看| 影音先锋男人在线资源| 国产精品久久久久久久电影| 老司机在线精品视频| 992tv快乐视频| 麻豆精品视频在线观看视频| 国精品无码人妻一区二区三区| 亚洲精品美国一| 伊人网中文字幕| 亚洲小视频在线观看| 国产一二三在线| 国产91精品入口17c| 先锋资源久久| av中文字幕网址| 国产精品美女www爽爽爽| 无码人妻丰满熟妇精品区| 日韩精品欧美激情| 欧亚在线中文字幕免费| 国产 高清 精品 在线 a| 欧美日韩少妇| 人妻巨大乳一二三区| 亚洲人成人一区二区在线观看| 91精东传媒理伦片在线观看| 国产亚洲精品一区二555| 日韩三级网址| 亚洲石原莉奈一区二区在线观看| 污视频网站在线免费| 国产欧美va欧美va香蕉在| 欧美色图一区| 91香蕉视频污版| 国产欧美日韩三级| 男人天堂视频网| 亚洲热线99精品视频| 新片速递亚洲合集欧美合集| 欧美日韩在线观看一区二区三区| 国产精品免费看| www.色多多| 色狠狠色噜噜噜综合网| 黄色小视频在线观看| 日韩av手机在线观看| 欧美激情在线精品一区二区三区| 国产精品天天av精麻传媒| 国产欧美日韩三区| 一级黄色片在线播放| 毛片精品免费在线观看| 中文字幕久久精品一区二区| 一二三四视频社区在线| 久久午夜电影网| 在线观看不卡的av| 久久亚洲欧美日韩精品专区| 日韩免费一级| 免费在线激情视频| 国产精品丝袜久久久久久app| 亚洲一区 中文字幕| 欧美成人精品xxx| 亲子伦视频一区二区三区| 天天摸天天碰天天添| 国产精品国产三级国产aⅴ入口 | 国产精品免费不| www.激情小说.com| 一区二区三区日韩在线观看| 免费观看黄色一级视频| 日本一区二区不卡| 91亚洲人成网污www| 极品白嫩少妇无套内谢| 欧美三级免费观看| 免费观看久久久久| 国产一级特黄a大片99| 日本视频一区二区| 久久久久久久久久99| 亚洲欧美日韩网| 激情久久免费视频| 中文字幕无码精品亚洲35| 国产精品嫩草久久久久| 丰满肥臀噗嗤啊x99av| 国产精品成人v| 黄色日韩在线| jizz日本在线播放| 精品国产乱码久久久久久1区2区| 欧美xx视频| 美女扒开大腿让男人桶| 国产精品天美传媒| 亚洲色图狠狠干| 亚洲va久久久噜噜噜|