本文將介紹兩種方式來實(shí)現(xiàn)功能插件化:
- Java SPI
- Spring factories
在整個(gè)插件化的方案中,會(huì)涉及到如下 3 個(gè)組成部分:
-
插件定義(即將插件定義為一個(gè)接口)
-
插件實(shí)現(xiàn)(即對(duì)插件接口的實(shí)現(xiàn))
這里對(duì)同一個(gè)插件定義,有兩個(gè)不同的實(shí)現(xiàn),即 2 個(gè)插件:cab5-charging-policy-general 和 cab5-charging-policy-vip,實(shí)現(xiàn)了不同的扣款策略。 -
支持插件插拔的平臺(tái)(因?yàn)椴恢澜猩叮们蚁冉小钢黜?xiàng)目」吧)
1、Java SPI
SPI 全稱 Service Provider Interface,中文譯為「服務(wù)提供者接口」,JDK 提供的一種服務(wù)發(fā)現(xiàn)機(jī)制,即為某個(gè)接口尋找具體的實(shí)現(xiàn)。
讓我們結(jié)合開篇提到的插件化方案所涉及 3 個(gè)組成部分,來說明下如何用 SPI 來實(shí)現(xiàn)插件化。
-
我們要將插件化的功能用接口來進(jìn)行定義,并接口打成一個(gè) jar 包。
-
實(shí)現(xiàn)【步驟1】中定義的接口,并將該實(shí)現(xiàn)打成一個(gè) jar 包。此時(shí)插件就已包裝完成,下一步就是「主項(xiàng)目」引入該 jar 包(即插件)。
這里有一個(gè)問題:
隨便一個(gè) jar 包就能成為一個(gè)插件嗎?
答案當(dāng)然是否定的。那問題又來了:
是通過什么來標(biāo)識(shí) jar 包是一個(gè)插件的呢?
我們需要在該 jar 包中 META-INF 目錄下創(chuàng)建 services 子目錄,同時(shí),在該子目錄下創(chuàng)建一個(gè)以接口(插件定義中的接口)名為文件名的文件,且文件中的內(nèi)容為接口實(shí)現(xiàn)類的全限定名,如下:
-
主項(xiàng)目引入插件并使用插件
首先我們?cè)凇钢黜?xiàng)目」中需要引入「插件定義」以及相關(guān)的「插件實(shí)現(xiàn)(即插件)」,如下:
最后我們?cè)賮碚f下,如何在「主項(xiàng)目」中使用插件,如下圖:
從圖中我們可以看到,Java SPI 通過 java.util.ServiceLoader 將插件接口(即 cab5-charging-policy jar 中的 CharginigPolicyPluging)的實(shí)現(xiàn)類全部(即 cab5-charging-policy-general jar 中的 ChargingPolicyGeneral 和 cab5-charging-policy-vip jar 中的 ChargingPolicyVip)加載,并通過該類的 iterator 方法將實(shí)現(xiàn)插件接口(即 cab5-charging-policy jar 中的 CharginigPolicyPluging)的插件進(jìn)行遍歷(也就是分別調(diào)用了 cab5-charging-policy-general jar 中的 ChargingPolicyGeneral 和 cab5-charging-policy-vip jar 中的 ChargingPolicyVip 的 charging 方法)。
這里又有一個(gè)問題:ServiceLoader 是如何找到「插件接口」的實(shí)現(xiàn)類的呢?
ServiceLoader 通過掃描「插件實(shí)現(xiàn)」的 jar 包中 META-INF/services 目錄下的文件,從而得知接口與實(shí)現(xiàn)的對(duì)應(yīng)關(guān)系,進(jìn)而找到了接口的所有實(shí)現(xiàn)類。
2、Spring factories
Spring factories 是 Spring Boot 一種解耦的擴(kuò)展機(jī)制,它仿照了 Java 的 SPI。采用 Spring factories 來實(shí)現(xiàn)功能插件化的過程與 Java SPI 非常類似。主要有以下 2 點(diǎn)不同:
-
將 jar 包標(biāo)識(shí)為插件的方式不同
Spring factories 需要我們?cè)谠?jar 包中的 META-INF 目錄下創(chuàng)建 spring.factories 文件,文件內(nèi)容為:接口=實(shí)現(xiàn)類的全限定名,如下:
-
「主項(xiàng)目」加載使用插件的方式不同
我們需要使用 spring-core 包里的 org.springframework.core.io.support.SpringFactoriesLoader 來加載插件,如下圖:
與 SPI 一樣,這里也進(jìn)一步說明下 SpringFactoriesLoader 是如何找到「插件接口」的實(shí)現(xiàn)類的:factories 是通過掃描「插件實(shí)現(xiàn)」的 jar 包中 META-INF/spring.factories 文件,從而得知接口與實(shí)現(xiàn)的對(duì)應(yīng)關(guān)系,進(jìn)而找到了接口的所有實(shí)現(xiàn)類。文章來源:http://www.zghlxwxcb.cn/news/detail-517350.html
3、示例代碼
本文的上方有提供對(duì)應(yīng)的示例代碼。文章來源地址http://www.zghlxwxcb.cn/news/detail-517350.html
到了這里,關(guān)于如何實(shí)現(xiàn)功能插件化的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!