1、前言
在之前的JVM 分析系列之類加載提到過 Java SPI 機制,主要是類加載器反雙親委派的實現(第三方包不在指定jdk路徑,一般類加載器無法加載,需要特殊的ContextClassLoader加載以便使用)。本次將對 SPI機制進行詳解,并結合案例介紹其在實際場景中具體使用。
2、什么是SPI機制?
- SPI(全稱:Service Provider Interface),是jdk內置的一種服務提供發(fā)現接口機制,旨在由第三方服務實現或擴展為組件,方便開發(fā)人員快速集成指定擴展組件滿足指定的需求。這對于應用或平臺擴展來說,無疑是一種成本較低、動態(tài)靈活的方案。
- SPI機制調度過程(業(yè)務調用方可根據加載的擴展實現類實現功能)
- 調用流程
3、實現方式及使用場景
鑒于目前實際項目涉及范圍,總結出的常見應用場景。
3.1 接口權限定文件名方式
- 即在resource文件下創(chuàng)建META/services/目錄,并在此目錄下新建文件,文件名稱為接口類權限定文件名,如 com.lgy.spidemo.serviceway.SpiService。(不好理解就是接口類的package地址 + 接口類名)
使用場景一:
- 場景描述:不同部門類型的員工需要從不同的考勤應用獲取出勤信息,如職能部門僅拉取釘釘考勤,業(yè)務部門需要拉取釘釘考勤的基礎上再結合自研考勤模塊數據匯總出勤結果。
- 實現方式:抽象通用拉取考勤接口,定義不同部門人員考勤統(tǒng)計實現類。
- 直接上代碼:
- 通用接口:
package com.lgy.spidemo.serviceway;
/**
* @description: 考勤接口
**/
public interface AttendanceService {
void pullAttendanceInfos();
}
- 職能部門考勤實現類
/**
* @description: 職能部門考勤實現
**/
public class FunctionAttendanceServiceImpl implements AttendanceService {
@Override
public void pullAttendanceInfos() {
System.out.println(" FunctionAttendanceService implements ...");
// 邏輯忽略
}
}
- 銷售部門考勤實現
/**
* @description: 銷售部門考勤實現
**/
public class SaleAttendanceServiceImpl implements AttendanceService {
@Override
public void pullAttendanceInfos() {
System.out.println(" SaleAttendanceService implements ...");
// 邏輯忽略
}
}
- 測試類
/**
* 1、項目的srcmainresources下創(chuàng)建META-INFservices目錄
* 2、META-INFservices的目錄下再增加一個配置文件,這個文件必須以接口的全限定類名保持一致 (com.lgy.spidemo.service.SpiService)
* 3、在配置文件中寫入具體實現類的全限定類名,如有多個便換行寫入 com.lgy.spidemo.service.impl.SaleAttendanceServiceImpl
com.lgy.spidemo.service.impl.FunctionAttendanceServiceImpl
**/
public class AttendanceServiceTest {
public static void main(String[] args) {
ServiceLoader< AttendanceService > services =
ServiceLoader.load(AttendanceService.class);
// 省略判斷人員部門類型邏輯
// 測試輸出結果,展示實現接口已加載
for (AttendanceService service : services) {
service.pullAttendanceInfos();
}
}
}
- 測試結果如下
// 兩個實現類均被加載成功,在實際使用時,可根據需要去調用不同的實現。
FunctionAttendanceService implements ...
SaleAttendanceService implements ....
- 實現類不要標注任何注解,不然Spring在初始化過程中掃描并加載,無法測試。
結合場景一分析:
- 此場景可以通過自定義實現類的方式滿足業(yè)務需求(不同部門的考勤規(guī)則),有助于業(yè)務實現快速迭代,同時也提升了服務架構的可拓展性。
- 考慮公司組織架構比較復雜,部門職責分的比較細,后續(xù)擴展幾率比較大,比如職能部門行政類和運營類標準細分,很可能會增加除了考勤之外的各種考核指標等,借鑒此方案可能簡單實現并比較方便集成,使得業(yè)務間減少依賴,實現解耦的設計模式,因此個人是比較偏向用此方案。
- 其它應用:如項目中常用的日志也是采用SPI機制,常見的common-logging的LogFatory就是標準SPI接口,有興趣的可以自行研究。
3.2 spring.factories方式
- 和上面一樣,需要在resource文件下創(chuàng)建META/services/目錄,并在此目錄下新建文件,區(qū)別在于文件名為 spring.factories 。
使用場景二
- 場景描述:針對于不同的開發(fā)端使用習慣展示不同的接口文檔,比如APP端習慣于Swagger,JAVA端喜歡dateway風格,就在不同實例展示不同接口文檔。此場景是我臆想出來。
- 實現方式:構建兩種版本的jar包,比如 1.0.0-swagger 、2.0.0-dataway,再對應的包內配置spring.factories內的config配置類。
- 代碼如下:
package com.lgy.spidemo.factoriesway;
import org.springframework.boot.autoconfigure.AutoConfigurationImportEvent;
import org.springframework.boot.autoconfigure.AutoConfigurationImportListener;
/**
* @description: 自動配置swagger
**/
public class SwaggetAutoConfiguration {
public SwaggetAutoConfiguration() {
System.out.println(" SwaggetAutoConfiguration init ...");
}
// 配置內容省略
}
/**
* @description: 自動配置dataway
**/
public class DataWayAutoConfiguration {
public DataWayAutoConfiguration() {
System.out.println(" DataWayAutoConfiguration init ...");
}
// 配置內容省略
}
/**
* resource/META-INFO/spring.factories 文件內容 *
* org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.lgy.spidemo.factoriesway.SwaggetAutoConfiguration
* 輸出結果:SwaggetAutoConfiguration init ...
**/
- 根據spring.factories內配置的類,在springboot啟動初始化過程中會自動加載對應的配置,實現所需的接口文檔。
結合場景二分析:
- spring.factories實現機制與上述方式一致,只是實現方式不同,本質目的是通過抽象化類的方式,實現解耦,最終便于擴展
- 其它使用場景:如spring-boot-autoconfigure-x.x.x.RELEASE.jar,就是通過此方式完成初始化加載。
4、總結
- 本次講解的兩種方式均是基于SPI機制,可見是多么受開發(fā)追捧。當然,還有很多種實現方式,我個人覺得最主要的還是能夠在自己的掌控范圍內去使用,畢竟有問題可以通過自己的學習理解去解決。
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。
舉報投訴
-
接口
+關注
關注
33文章
8598瀏覽量
151157 -
SPI
+關注
關注
17文章
1706瀏覽量
91581 -
代碼
+關注
關注
30文章
4788瀏覽量
68612 -
Package
+關注
關注
0文章
26瀏覽量
10497 -
spring
+關注
關注
0文章
340瀏覽量
14343
發(fā)布評論請先 登錄
相關推薦
關于SPI通訊的精講 SPI協(xié)議的特點和工作機制
1、SPI協(xié)議簡介 1.1 SPI協(xié)議概括 SPI,是英語Serial Peripheral interface的縮寫,顧名思義就是串行外圍設備接口。是Motorola首先在其MC68HCXX系列
SPI總線學習筆記
SPI是一種全雙工的串行通信總線,最早由Motorola提出,雖然應用廣泛,但沒有一個統(tǒng)一的總線標準。相較于IIC總線,SPI具有通信速度快、協(xié)議靈活、無復雜的總線仲裁機制、支持中斷等優(yōu)點,但缺點也
發(fā)表于 09-20 15:17
?1084次閱讀
聊聊Dubbo - Dubbo可擴展機制實戰(zhàn)
OSGI容器Dubbo作為一個框架,不希望強依賴其他的IoC容器,比如Spring,Guice。OSGI也是一個很重的實現,不適合Dubbo。最終Dubbo的實現參考了Java原生的SPI機制,但對其
發(fā)表于 06-04 17:33
RT_SFUD_SPI_MAX_HZ到底是什么作用機制呢?
設定會導致spi clk 的波形畸變。設定 13mhz時波形:示波器顯示頻率 25mhz設定 13mhz時波形:示波器顯示頻率 50mhz疑問:1:RT_SFUD_SPI_MAX_HZ 到底是什么作用機制2:
發(fā)表于 04-14 10:08
SPI模式下MMC卡的讀寫機制
SPI模式下MMC卡的讀寫機制
多媒體卡MMC(MultiMedia Card)是由美國SanDisk公司和德國Simens公司于1997年共同開發(fā)的一種多功能Flash存儲設備。基于ARM7芯
發(fā)表于 03-29 15:13
?1212次閱讀
SPI總線協(xié)議的工作機制解析
SPI,串行外圍設備接口,是Motorola公司推出的一種同步串行接口技術.SPI總線在物理上是通過接在外圍設備微控制器(PICmicro)上面的微處理控制單元(MCU)上叫作同步串行端口
發(fā)表于 08-25 17:38
?1408次閱讀
SPI通信簡介
目錄(?)[-]SPI簡介SPI特點1采用主-從模式Master-Slave 的控制方式2采用同步方式Synchronous傳輸數據3數據交換Data Exchanges4 SPI有四種傳輸模式5
發(fā)表于 12-22 19:14
?9次下載
源碼級深度理解Java SPI
SPI 配置:Java SPI 機制約定的配置文件,提供查找服務實現類的邏輯。配置文件必須置于 META-INF/services 目錄中,并且,文件名應與服務提供者接口的完全限定名保持一致。文件中的每一行都有一個實現服務類的詳
JDK內置的一種服務SPI機制
SPI(Service Provider Interface)是JDK內置的一種服務提供發(fā)現機制,可以用來啟用框架擴展和替換組件,主要用于框架中開發(fā),例如Dubbo、Spring
基于spring的SPI擴展機制是如何實現的?
基本上,你一說是基于 spring 的 SPI 擴展機制,再把spring.factories文件和EnableAutoConfiguration提一下,那么這個問題就答的八九不離十了。
可插拔組件設計機制—SPI介紹
SPI 的全稱是 Service Provider Interface, 即提供服務接口;是一種服務發(fā)現機制,SPI 的本質是將接口實現類的全限定名配置在文件中,并由服務加載器讀取配置文件,加載實現類。
Java、Spring、Dubbo三者SPI機制的原理和區(qū)別
其實我之前寫過一篇類似的文章,但是這篇文章主要是剖析dubbo的SPI機制的源碼,中間只是簡單地介紹了一下Java、Spring的SPI機制,并沒有進行深入,所以本篇就來深入聊一聊這三
SPI傳輸原理 SPI傳輸機制
SPI 傳輸機制 從圖可以看出,主機和從機都有一個串行移位寄存器,主機通過向它的 SPI 串行寄存器寫入一個字節(jié)來發(fā)起一次傳輸。寄存器通過 MOSI 信號線將字節(jié)傳送給從機,從機也將自己的移位寄存器
評論