從攜程Apollo客戶端源碼學(xué)到的SPI知識(shí)(二)

知識(shí)點(diǎn):SPI(Service Provider Interfaces)到底是啥玩意翘地,簡(jiǎn)單一句話概括就是用來(lái)被第三方實(shí)現(xiàn)的 API蛛倦。有點(diǎn)抽象年柠,我們先仿照Apollo客戶端寫(xiě)個(gè)簡(jiǎn)單例子吧

場(chǎng)景舉例

假設(shè)有一個(gè)短信平臺(tái)需要對(duì)接多家SMS渠道用來(lái)發(fā)送短信扰楼。當(dāng)然這個(gè)場(chǎng)景不一定要用SPI機(jī)制來(lái)實(shí)現(xiàn),畢竟條條大路通羅馬划鸽。本案例只是用來(lái)介紹SPI的使用方式方法输莺。

工程目錄

fg-great-spi.png

fg-spi-sms-interface 是接口部分,提供了一個(gè)默認(rèn)實(shí)現(xiàn)裸诽,fg-spi-sms-provider是自定義的一個(gè)實(shí)現(xiàn)

fg-spi-sms-interface

接口部分的代碼結(jié)構(gòu)如下嫂用,本模塊假設(shè)為通用實(shí)現(xiàn)

fg-spi-sms-interface.png

我們首先提供一個(gè)短信發(fā)送的接口或者抽象類,下面我們新建一個(gè)接口如下:

package com.example.fg.sms;

/**
 * @author cattle -  稻草鳥(niǎo)人
 * @date 2020/4/23 下午12:49
 */
public interface MessageServiceProvider {

    /**
     *  發(fā)送短息
     * @param message 短信內(nèi)容
     */
    void sendMessage(String message);

}

其次我們對(duì)這個(gè)接口做一個(gè)默認(rèn)實(shí)現(xiàn)如下:

package com.example.fg.sms;

/**
 * @author cattle -  稻草鳥(niǎo)人
 * @date 2020/4/23 下午12:57
 */
public class DefaultMessageServiceProvider implements MessageServiceProvider {
    @Override
    public void sendMessage(String message) {
        System.out.println("default:::" + message);
    }
}

再次丈冬,我們?cè)趓esources/META-INF/services目錄下新建一個(gè)文件嘱函,名為com.example.fg.sms.MessageServiceProvider此名字和接口同名,內(nèi)容為com.example.fg.sms.DefaultMessageServiceProvider是我們的默認(rèn)實(shí)現(xiàn)

最后,我們就可以通過(guò)ServiceLoader.load埂蕊。例如往弓,通過(guò)如下代碼實(shí)現(xiàn)執(zhí)行我們默認(rèn)方法實(shí)現(xiàn)的方法

package com.example.fg.sms;

import java.util.ServiceLoader;

/**
 * @author cattle -  稻草鳥(niǎo)人
 * @date 2020/4/23 下午12:52
 */
public class MessageServiceFactory {

    private ServiceLoader<MessageServiceProvider> serviceProviders = ServiceLoader.load(MessageServiceProvider.class);

    public void sendMessage(String message) {

        for (MessageServiceProvider serviceProvider : serviceProviders) {
            serviceProvider.sendMessage(message);
        }

    }
}

接口測(cè)試

package com.example.fg.sms;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class MessageServiceFactoryTest {

    @Test
    void sendMessage() {
        MessageServiceFactory factory = new MessageServiceFactory();
        factory.sendMessage("hello spi");
    }
}

輸出:

default:::hello spi

fg-spi-sms-provider

本模塊是另外一個(gè)實(shí)現(xiàn),用來(lái)模擬某供應(yīng)商針對(duì)接口實(shí)現(xiàn)自己的短信發(fā)送方法蓄氧。

fg-spi-sms-provider.png

接口實(shí)現(xiàn)

package com.example.fg.sms;

/**
 * @author cattle -  稻草鳥(niǎo)人
 * @date 2020/4/23 下午1:06
 */
public class MyMessageServiceProvider implements MessageServiceProvider {
    @Override
    public void sendMessage(String message) {
        System.out.println("MyMessage:::" + message);
    }
}

本模塊我們依然要在resources/META-INF/services目錄下新建一個(gè)名為com.example.fg.sms.MessageServiceProvider內(nèi)容就是我們自己的實(shí)現(xiàn)函似,即com.example.fg.sms.MyMessageServiceProvider

接口測(cè)試

package com.example.fg.sms;

import org.junit.jupiter.api.Test;

class MessageServiceFactoryTest {

    @Test
    void sendMessage() {
        MessageServiceFactory factory = new MessageServiceFactory();
        factory.sendMessage("hello spi");
    }
}

輸出:

MyMessage:::hello spi
default:::hello spi

其他SPI場(chǎng)景

目前開(kāi)源的很多框架里面,如果大家仔細(xì)觀察的話匀们,SPI用到了非常多的地方缴淋,比如dubbo准给,motan泄朴,日志處理框架重抖,還有JDBC Driver等等。

總結(jié)

經(jīng)過(guò)上面的案例其實(shí)已經(jīng)很清楚了祖灰,寫(xiě)一個(gè)接口钟沛,然后自己去實(shí)現(xiàn),另外在resources/META-INF/services目錄下新建一個(gè)文件夾局扶,內(nèi)容是具體的實(shí)現(xiàn)恨统。然后通過(guò)ServiceLoader.load之后調(diào)用具體的實(shí)現(xiàn)。

思考

  1. 多個(gè)實(shí)現(xiàn)的情況下三妈,如何只執(zhí)行其中一種實(shí)現(xiàn)呢畜埋?比如MyMessageServiceProviderDefaultMessageServiceProvider兩個(gè)實(shí)現(xiàn)只執(zhí)行其中一個(gè)sendMessage方法

  2. apollo-client中對(duì)于SPI的具體應(yīng)用,和我們當(dāng)前的例子是否有差別呢畴蒲?

源碼

https://github.com/cattles/fucking-great-spi

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末悠鞍,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子模燥,更是在濱河造成了極大的恐慌咖祭,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔫骂,死亡現(xiàn)場(chǎng)離奇詭異么翰,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)辽旋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門浩嫌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人补胚,你說(shuō)我怎么就攤上這事固该。” “怎么了糖儡?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵伐坏,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我握联,道長(zhǎng)桦沉,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任金闽,我火速辦了婚禮纯露,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘代芜。我一直安慰自己埠褪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著钞速,像睡著了一般贷掖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上渴语,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天苹威,我揣著相機(jī)與錄音,去河邊找鬼驾凶。 笑死牙甫,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的调违。 我是一名探鬼主播窟哺,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼技肩!你這毒婦竟也來(lái)了脏答?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤亩鬼,失蹤者是張志新(化名)和其女友劉穎殖告,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體雳锋,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡黄绩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了玷过。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爽丹。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖辛蚊,靈堂內(nèi)的尸體忽然破棺而出粤蝎,到底是詐尸還是另有隱情,我是刑警寧澤袋马,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布初澎,位于F島的核電站,受9級(jí)特大地震影響虑凛,放射性物質(zhì)發(fā)生泄漏碑宴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一桑谍、第九天 我趴在偏房一處隱蔽的房頂上張望延柠。 院中可真熱鬧,春花似錦锣披、人聲如沸贞间。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)增热。三九已至整以,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間钓葫,已是汗流浹背悄蕾。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工票顾, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留础浮,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓奠骄,卻偏偏與公主長(zhǎng)得像豆同,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子含鳞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容