Java SPI機(jī)制原理及代碼實(shí)例
SPI的全名為:Service Provider Interface,大多數(shù)開發(fā)人員可能不熟悉,因?yàn)檫@個(gè)是針對廠商或者插件的。在java.util.ServiceLoader的文檔里有比較詳細(xì)的介紹。
簡單的總結(jié)下 Java SPI 機(jī)制的思想。我們系統(tǒng)里抽象的各個(gè)模塊,往往有很多不同的實(shí)現(xiàn)方案,比如日志模塊的方案,xml解析模塊、jdbc模塊的方案等。面向的對象的設(shè)計(jì)里,我們一般推薦模塊之間基于接口編程,模塊之間不對實(shí)現(xiàn)類進(jìn)行硬編碼。
一旦代碼里涉及具體的實(shí)現(xiàn)類,就違反了可拔插的原則,如果需要替換一種實(shí)現(xiàn),就需要修改代碼。為了實(shí)現(xiàn)在模塊裝配的時(shí)候能不在程序里動態(tài)指明,這就需要一種服務(wù)發(fā)現(xiàn)機(jī)制。
Java SPI 就是提供這樣的一個(gè)機(jī)制:為某個(gè)接口尋找服務(wù)實(shí)現(xiàn)的機(jī)制。有點(diǎn)類似IOC的思想,就是將裝配的控制權(quán)移到程序之外,在模塊化設(shè)計(jì)中這個(gè)機(jī)制尤其重要。
Java SPI 的具體約定為:當(dāng)服務(wù)的提供者,提供了服務(wù)接口的一種實(shí)現(xiàn)之后,在jar包的META-INF/services/目錄里同時(shí)創(chuàng)建一個(gè)以服務(wù)接口命名的文件。該文件里就是實(shí)現(xiàn)該服務(wù)接口的具體實(shí)現(xiàn)類。
而當(dāng)外部程序裝配這個(gè)模塊的時(shí)候,就能通過該jar包META-INF/services/里的配置文件找到具體的實(shí)現(xiàn)類名,并裝載實(shí)例化,完成模塊的注入。
基于這樣一個(gè)約定就能很好的找到服務(wù)接口的實(shí)現(xiàn)類,而不需要再代碼里制定。jdk提供服務(wù)實(shí)現(xiàn)查找的一個(gè)工具類:java.util.ServiceLoader。
1.common-logging
apache最早提供的日志的門面接口。只有接口,沒有實(shí)現(xiàn)。具體方案由各提供商實(shí)現(xiàn), 發(fā)現(xiàn)日志提供商是通過掃描 META-INF/services/org.apache.commons.logging.LogFactory配置文件,通過讀取該文件的內(nèi)容找到日志提工商實(shí)現(xiàn)類。
只要我們的日志實(shí)現(xiàn)里包含了這個(gè)文件,并在文件里制定 LogFactory工廠接口的實(shí)現(xiàn)類即可。關(guān)注Java技術(shù)棧微信公眾號,在后臺回復(fù)關(guān)鍵字:Java,可以獲取更多棧長整理的Java技術(shù)干貨。
2.jdbc
jdbc4.0以前, 開發(fā)人員還需要基于Class.forName("xxx")的方式來裝載驅(qū)動,jdbc4也基于spi的機(jī)制來發(fā)現(xiàn)驅(qū)動提供商了,可以通過META-INF/services/java.sql.Driver文件里指定實(shí)現(xiàn)類的方式來暴露驅(qū)動提供者。
一個(gè)內(nèi)容管理系統(tǒng)有一個(gè)搜索模塊。是基于接口編程的。搜索的實(shí)現(xiàn)可能是基于文件系統(tǒng)的搜索,也可能是基于數(shù)據(jù)庫的搜索
接口定義如下:
package my.xyz.spi;
import java.util.List;
public interface Search {
public List serch(String keyword);
}
A公司采用文件系統(tǒng)搜索的方式實(shí)現(xiàn)了 Search接口,B公司采用了數(shù)據(jù)庫系統(tǒng)的方式實(shí)現(xiàn)了Search接口。
A公司實(shí)現(xiàn)的類:com.A.spi.impl.FileSearch
B公司實(shí)現(xiàn)的類:com.B.spi.impl.DatabaseSearch
那么A公司發(fā)布 實(shí)現(xiàn)jar包時(shí),則要在jar包中META-INF/services/my.xyz.spi.Search文件中寫下如下內(nèi)容:
com.A.spi.impl.FileSearch
那么B公司發(fā)布 實(shí)現(xiàn)jar包時(shí),則要在jar包中META-INF/services/my.xyz.spi.Search文件中寫下如下內(nèi)容:
com.B.spi.impl.DatabaseSearch
下面是 SPI 測試代碼:
package com.xyz.factory;
import java.util.Iterator;
import java.util.ServiceLoader;
import my.xyz.spi.Search;
public class SearchFactory {
private SearchFactory() {
}
public static Search newSearch() {
Search search = null;
ServiceLoader<Search> serviceLoader = ServiceLoader.load(Search.class);
Iterator<Search> searchs = serviceLoader.iterator();
if (searchs.hasNext()) {
search = searchs.next();
}
return search;
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
如何使用MybatisPlus快速進(jìn)行增刪改查詳解
增刪改查在日常開發(fā)中是再正常不多的一個(gè)需求了,下面這篇文章主要給大家介紹了關(guān)于如何使用MybatisPlus快速進(jìn)行增刪改查的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08
spring?boot?實(shí)現(xiàn)一個(gè)?禁止重復(fù)請求的方法
這篇文章主要介紹了spring?boot?實(shí)現(xiàn)一個(gè)?禁止重復(fù)請求,當(dāng)重復(fù)請求該方法時(shí),會返回"Duplicate?request",避免重復(fù)執(zhí)行相同的操作,需要的朋友可以參考下2024-03-03
Java中的ReentrantReadWriteLock實(shí)現(xiàn)原理詳解
這篇文章主要介紹了Java中的ReentrantReadWriteLock實(shí)現(xiàn)原理詳解,讀寫鎖實(shí)現(xiàn)了接口ReadWriteLock,適合于讀多寫少的情況,支持公平鎖和非公平鎖,支持可沖入(進(jìn)入讀鎖后可再進(jìn)入讀鎖,進(jìn)入寫鎖后可再進(jìn)入寫鎖和讀鎖),需要的朋友可以參考下2024-01-01
基于java實(shí)現(xiàn)顏色拾色器并打包成exe
這篇文章主要為大家詳細(xì)介紹了如何基于java編寫一個(gè)簡單的顏色拾色器并打包成exe文件,文中的示例代碼講解詳細(xì),需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-10-10
servlet之cookie簡介_動力節(jié)點(diǎn)Java學(xué)院整理
Cookie技術(shù)誕生以來,它就成了廣大網(wǎng)絡(luò)用戶和Web開發(fā)人員爭論的一個(gè)焦點(diǎn)。下面這篇文章主要給大家介紹了關(guān)于servlet之cookie簡介的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。2017-07-07
SpringMVC基于阻塞隊(duì)列LinkedBlockingQueue的同步長輪詢功能實(shí)現(xiàn)詳解
這篇文章主要介紹了SpringMVC基于阻塞隊(duì)列LinkedBlockingQueue的同步長輪詢功能實(shí)現(xiàn)詳解,本文介紹的也是生產(chǎn)者消費(fèi)者的一種實(shí)現(xiàn),生產(chǎn)者不必是一個(gè)始終在執(zhí)行的線程,它可以是一個(gè)接口,接受客戶端的請求,向隊(duì)列中插入消息,需要的朋友可以參考下2023-07-07
Eclipse下編寫java程序突然不會自動生成R.java文件和包的解決辦法
這篇文章主要介紹了Eclipse下編寫java程序突然不會自動生成R.java文件和包的解決辦法 的相關(guān)資料,需要的朋友可以參考下2016-01-01
Java使用Lambda表達(dá)式查找list集合中是否包含某值問題
Java使用Lambda表達(dá)式查找list集合中是否包含某值的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06

