記一次 JDK SPI 配置不生效的問題 → 這麼簡單都不會,還是回家養豬吧

青石路發表於2022-05-30

開心一刻

  今天去幼兒園接小侄女,路上聊起了天

  小侄女:小叔,今天我吃東西被老師發現了

  我:老師說了什麼

  小侄女:她說拿出來,跟小朋友一起分享

  我:那你拿出來了嗎

  小侄女一臉可憐的看向我,說道:沒有,我沒有那麼多鼻屎

記一次 JDK SPI 配置不生效的問題 → 這麼簡單都不會,還是回家養豬吧

SPI

  概念

  SPI 全稱 Service Provider Interface ,直譯過來就是: 服務提供介面 ,是不是有點抽象?

  簡單點理解,Java SPI 就是提供這樣的一個機制:為某個介面尋找服務實現的機制

  還是抽象?我們往下看它的具體實現就好理解了

  實現三板斧

  1、介面與實現

    Animal 介面

    Dog 實現

    Cat 實現

  2、配置檔案

    配置檔案有點講究,需要按這套規則來

    2.1 在 src/main/resources/ 下建立目錄: /META-INF/services ,位置和名字都必須嚴格按這個來,一字都不能差

    2.2 在 /META-INF/services 目錄下建立一個以介面全限定類名為名的檔案: com.qsl.service.Animal ,沒有額外的字尾

    2.3 將介面實現類的全限定類名寫入到 2.2 建立的檔案中,一個實現佔一行

  3、ServiceLoader 載入

    通過 ServiceLoader 進行載入,程式碼很簡單,如下所示

    正常情況下會輸出如下內容

  示例工程結構如下

  至此,對 SPI 的感覺是不是沒那麼抽象了

  簡單理解, Java SPI 是 基於介面的程式設計 + 策略模式 + 配置檔案 實現的動態載入機制

  使用場景

  不太好概括,一千個人眼中有一千個哈姆雷特

  但是我們可以通過一些案例來形成自己的概括

  1、DriverManager

    不知道大家還記得 JDBC 的寫法嗎

    我們去跟下 DriverManager 的原始碼

記一次 JDK SPI 配置不生效的問題 → 這麼簡單都不會,還是回家養豬吧

    我們再看下 MySQL 驅動的包結構

  2、SLF4J

    具體原始碼我就不帶大家去跟了,有興趣的可以去看看:從原始碼來理解slf4j的繫結,以及logback對配置檔案的載入 中的問題1

  3、Spring SPI

     Spring 有自己的 SPI 實現機制,和 JDK SPI 略有不同

     Spring 是在 src/main/resources/META-INF 目錄下建立 spring.factories ,裡面以鍵值對的方式存放多個實現,類似如下

  4、Dubbo SPI

     Dubbo 又有自己的一套實現,配置檔案需要放到 META-INF/dubbo 目錄下

    具體細節可檢視其官方文件:Dubbo SPI

問題重現

  此刻,大家是不是覺得 JDK SPI 很簡單?

  但正是這麼簡單的東西,樓主都碰到了問題,如下圖所示

記一次 JDK SPI 配置不生效的問題 → 這麼簡單都不會,還是回家養豬吧

  當時人就懵了!!!

問題排查

  一度懷疑是不是 JDK SPI 還有額外的配置

  因為是工作中的專案出了這個問題,所以我自建了一個 demo 來驗證 實現三板斧 

  結果 demo 的執行是沒問題的,這也就說明 JDK SPI 的實現就只有那三板斧,那問題出在哪了?

  本著快速解決問題的目的,我換了一種實現方式,採用 Spring SPI 

  結果依然是有問題,同樣是讀不到 spring.factories 中的配置

  正在一籌莫展之際,直覺告訴我是不是 maven 構建出了問題,所以我對專案進行了 package ,然後去看了下打好的包的目錄結構

   META-INF 目錄下的 com.qsl.service.Animal 檔案了?

  肯定是 pom.xml 配置不對

  我是萬萬沒想到 pom.xml 會進行如上的配置(後面問了老同事,沒特別的原因,就是簡單的認為只會有 xml 和 yml 配置檔案)

  此刻,相信大家都知道怎麼改了吧(去掉<includes>標籤,或者在<includes>中加上)

  然而樓主沒用採用上述兩種方案的任一一個,也沒有改 pom.xml ,就問你氣不氣?

總結

  1、 JDK SPI 的使用,就那三板斧,如果出了問題,不用想,肯定不是 JDK SPI 的問題

  2、關於 SPI 的使用場景,樓主仍然不做概括(太菜,概括不好),大家自行去概括

  3、關於 pom.xml 

    樓主之前寫過一篇:Maven pom.xml中的元素modules、parent、properties以及import

    但就是沒講 <build> ,下次補上,你們記得提醒我哦!

記一次 JDK SPI 配置不生效的問題 → 這麼簡單都不會,還是回家養豬吧

 

相關文章