最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java利用SPI實(shí)現(xiàn)解耦的示例詳解

 更新時(shí)間:2023年04月07日 11:20:30   作者:少年的我  
SPI的全稱(chēng)是服務(wù)提供接口,可以用其來(lái)啟動(dòng)框架的擴(kuò)展和替換組件。本文將利用SPI實(shí)現(xiàn)解耦,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下

概述

SPI的全稱(chēng)是服務(wù)提供接口,可以用其來(lái)啟動(dòng)框架的擴(kuò)展和替換組件。

其本質(zhì)是利用 接口實(shí)現(xiàn)+策略模式+配置文件來(lái)實(shí)現(xiàn)對(duì)實(shí)現(xiàn)類(lèi)的動(dòng)態(tài)加載。

在具體的使用中,存在一些約定:

(1)規(guī)定在 classPath 的 META-INF/services/ 下,創(chuàng)建該接口的全名稱(chēng)文件

(2)在該文件中,寫(xiě)入該接口實(shí)現(xiàn)類(lèi)全稱(chēng)(路徑+文件名),多個(gè)實(shí)現(xiàn)類(lèi)的話,分行寫(xiě)。

(3)用的2時(shí)候,使用 java.util.ServiceLoader 的 load(Interface.class),獲取到實(shí)現(xiàn)類(lèi),就可以使用了。

值得注意的是,接口實(shí)現(xiàn)類(lèi)必須有一個(gè)不帶參數(shù)的構(gòu)造方法。

實(shí)現(xiàn)案例

在本應(yīng)用中,存在兩個(gè)模塊,分別為A模塊和B模塊,這兩個(gè)模塊中,A模塊是主模塊,B是從模塊,B模塊是依賴(lài)A模塊的。但是在目前有一個(gè)類(lèi),該類(lèi)中實(shí)現(xiàn)在B模塊中,A模塊需要調(diào)用這個(gè)類(lèi)的函數(shù),而模塊不能再依賴(lài)B模塊,此時(shí)需要進(jìn)行解耦。在本實(shí)現(xiàn)中,利用SPI的方式進(jìn)行解耦實(shí)現(xiàn)。具體實(shí)現(xiàn)方案為:

(1)在A模塊新建一個(gè)接口:MyLogAppender,具體實(shí)現(xiàn)為:

/**
 * @author Huang gen(kenfeng)
 * @description 自定義的appender接口
 * @Since 2021/02/21
 **/

public interface MyLogAppender {

    /**
     * 獲取實(shí)現(xiàn)的appender
     * @return  返回新建的appender對(duì)象
     * */
    Appender getAppender();
}

這個(gè)接口很簡(jiǎn)單,只是返回一個(gè)appender的對(duì)象。對(duì)于對(duì)象的實(shí)際操作,在接口的實(shí)現(xiàn)中進(jìn)行操作。

(2)在B模塊添加對(duì)這個(gè)接口的實(shí)現(xiàn),具體的操作為:

/**
 * @author Huang gen(kenfeng)
 * @description 自定義的appender
 * @Since 2021/02/21
 **/
@Component
public class MeshLogAppender extends UnsynchronizedAppenderBase<ILoggingEvent> implements MyLogAppender,ApplicationContextAware {

    private ApplicationContext applicationContext;

    public MeshLogAppender(){ }

    @Override
    public Appender getAppender() {
        MeshLogAppender meshLogAppender = new MeshLogAppender();
        return meshLogAppender;
    }

    @Override
    protected void append(ILoggingEvent iLoggingEvent) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String std = simpleDateFormat.format(new Date(Long.parseLong(String.valueOf(iLoggingEvent.getTimeStamp()))));
        String log = std + "\t" + iLoggingEvent.getLevel() +"\t"+"--- ["+ iLoggingEvent.getThreadName()+"]\t"+iLoggingEvent.getCallerData()[0]+":\t "+iLoggingEvent.getMessage();
        FlowMessage input = new FlowMessage();
        MeshFlowService meshFlowService = SandboxSystemServiceFactory.getService(MeshFlowService.class);
        Map<String, Object> body = new HashMap<>(2);
        body.put("log",log);
        input.setTenantCode(DefaultTenant.get());
        input.setAppCode("epoch");
        input.setFlowCode("log_broadcast");
        input.setBody(body);
        FlowMessage output = meshFlowService.process(input);
        if(!StringUtils.isEmpty(output.getErrorMessage())){
            throw new RuntimeException("發(fā)布日志時(shí),廣播失敗");
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

在該接口的申明和接口的實(shí)現(xiàn)中,存在一些小的技巧的實(shí)現(xiàn)。在接口中,只聲明一個(gè)類(lèi)的獲取,并沒(méi)有實(shí)現(xiàn)具體的方法。在實(shí)現(xiàn)類(lèi)中,對(duì)這個(gè)類(lèi)進(jìn)行實(shí)例化,new一個(gè)新的類(lèi)并返回,此時(shí)用戶(hù)根據(jù)這個(gè)get方法就可以拿到這個(gè)實(shí)現(xiàn)類(lèi),然后進(jìn)行實(shí)現(xiàn)類(lèi)的一些操作。這樣寫(xiě)可以帶來(lái)兩個(gè)好處: i. 代碼更簡(jiǎn)潔,接口的代碼簡(jiǎn)單易懂 ii. 可以在實(shí)現(xiàn)類(lèi)的構(gòu)造方法中注入一些參數(shù),當(dāng)用戶(hù)使用時(shí),直接在get方法里面注入即可。

(3) 在實(shí)現(xiàn)類(lèi)所在文件夾下,也就是sandbox-app-epoch-starter中添加一個(gè)配置文件,其配置文件的路徑默認(rèn)為: resources/META-INF/services/,在這個(gè)文件夾下新建一個(gè)問(wèn)題,文件名為接口的路徑,內(nèi)容是實(shí)現(xiàn)類(lèi)的路徑。由此可以實(shí)現(xiàn)接口-->實(shí)現(xiàn)類(lèi)的映射。

如上圖中,文件名為:com.alibaba.halo.sandbox.app.util.MyLogAppender

其文件中的內(nèi)容為:com.alibaba.lattice2.epoch.util.MeshLogAppender

其原理是,當(dāng)用戶(hù)使用接口時(shí),會(huì)掃描項(xiàng)目下的所有文件,查找文件名為com.alibaba.halo.sandbox.app.util.MyLogAppender,然后根據(jù)其內(nèi)容來(lái)查找到相關(guān)的實(shí)現(xiàn)類(lèi)

(4)在A,可以直接使用接口來(lái)進(jìn)行調(diào)用,具體實(shí)現(xiàn)如下:

				ServiceLoader<MyLogAppender> myLoaderInterfaceServiceLoader = ServiceLoader.load(MyLogAppender.class);
        Iterator<MyLogAppender> myLoaderInterfaceIterator = myLoaderInterfaceServiceLoader.iterator();
        while (myLoaderInterfaceIterator.hasNext()){
            MyLogAppender myLoaderInterface = myLoaderInterfaceIterator.next();

            Appender newAppender = myLoaderInterface.getAppender();
            newAppender.setName("application");
            newAppender.setContext(loggerContext);
            newAppender.start();
            rootLogger.addAppender(newAppender);
        }

從上面可以看到,其可以直接調(diào)用MyLogAppender接口,利用這個(gè)接口獲取的Appender,之后直接賦值即可。

優(yōu)勢(shì)和不足

優(yōu)點(diǎn):可以實(shí)現(xiàn)代碼的解耦

缺點(diǎn):存在多個(gè)實(shí)現(xiàn)類(lèi)的話,無(wú)法根據(jù)某個(gè)參數(shù)或者標(biāo)志位獲取實(shí)例,只能通過(guò)遍歷獲取,沒(méi)有實(shí)現(xiàn)所謂的懶加載

到此這篇關(guān)于Java利用SPI實(shí)現(xiàn)解耦的示例詳解的文章就介紹到這了,更多相關(guān)Java SPI解耦內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SSM框架中entity mapper dao service controller層的使用

    SSM框架中entity mapper dao service controll

    這篇文章主要介紹了SSM框架中entity mapper dao service controller層的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • Java 實(shí)現(xiàn)一個(gè)漢諾塔實(shí)戰(zhàn)練習(xí)

    Java 實(shí)現(xiàn)一個(gè)漢諾塔實(shí)戰(zhàn)練習(xí)

    漢諾塔是源于印度一個(gè)古老傳說(shuō)的益智玩具。大梵天創(chuàng)造世界時(shí)做了三根石柱,在一根柱子上從下往上按大小順序摞著64片黃金圓盤(pán)。大梵天命令婆羅門(mén)把圓盤(pán)從下面開(kāi)始按大小順序重新擺放在另一根柱子上。并且規(guī)定,在小圓盤(pán)上不能放大圓盤(pán),三根柱子之間一次只能移動(dòng)一個(gè)圓盤(pán)
    2021-10-10
  • Mybatis查詢(xún)語(yǔ)句返回對(duì)象和泛型集合的操作

    Mybatis查詢(xún)語(yǔ)句返回對(duì)象和泛型集合的操作

    這篇文章主要介紹了Mybatis查詢(xún)語(yǔ)句返回對(duì)象和泛型集合的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java實(shí)現(xiàn)文件圖片的預(yù)覽和下載功能

    Java實(shí)現(xiàn)文件圖片的預(yù)覽和下載功能

    這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)文件圖片的預(yù)覽和下載功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-04-04
  • 快速解決VS Code報(bào)錯(cuò):Java 11 or more recent is required to run. Please download and install a recent JDK

    快速解決VS Code報(bào)錯(cuò):Java 11 or more recent is required to run. Ple

    這篇文章主要介紹了快速解決VS Code報(bào)錯(cuò):Java 11 or more recent is required to run. Please download and install a recent JDK的相關(guān)資料,需要的朋友可以參考下
    2020-09-09
  • Java中Velocity快速對(duì)變量中的引號(hào)特殊字符進(jìn)行轉(zhuǎn)義

    Java中Velocity快速對(duì)變量中的引號(hào)特殊字符進(jìn)行轉(zhuǎn)義

    Velocity是一個(gè)基于Java的模板引擎,與Freemarker類(lèi)似,這篇文章主要介紹了Java中Velocity如何對(duì)變量中的引號(hào)特殊字符進(jìn)行轉(zhuǎn)義,主要記錄一下在使用中碰到的要對(duì)引號(hào)特殊字符進(jìn)行轉(zhuǎn)義的問(wèn)題,需要的朋友可以參考下
    2023-07-07
  • java防反編譯最簡(jiǎn)單的技巧分享

    java防反編譯最簡(jiǎn)單的技巧分享

    這篇文章主要給大家分享了關(guān)于java防反編譯最簡(jiǎn)單的技巧,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • Spring中利用SchedulingConfigurer實(shí)現(xiàn)動(dòng)態(tài)定時(shí)任務(wù)配置的示例

    Spring中利用SchedulingConfigurer實(shí)現(xiàn)動(dòng)態(tài)定時(shí)任務(wù)配置的示例

    定時(shí)任務(wù)是一項(xiàng)至關(guān)重要的功能,它們使得我們能夠按照預(yù)定的時(shí)間執(zhí)行特定的任務(wù),本文主要介紹了Spring中利用SchedulingConfigurer實(shí)現(xiàn)動(dòng)態(tài)定時(shí)任務(wù)配置的示例,感興趣的可以了解一下
    2024-05-05
  • java 使用poi動(dòng)態(tài)導(dǎo)出的操作

    java 使用poi動(dòng)態(tài)導(dǎo)出的操作

    這篇文章主要介紹了java 使用poi動(dòng)態(tài)導(dǎo)出的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • IntelliJ?IDEA?2022.1.1創(chuàng)建java項(xiàng)目的詳細(xì)方法步驟

    IntelliJ?IDEA?2022.1.1創(chuàng)建java項(xiàng)目的詳細(xì)方法步驟

    最近安裝了IntelliJ IDEA 2022.1.1,發(fā)現(xiàn)新版本的窗口還有些變化的,所以下面這篇文章主要給大家介紹了關(guān)于IntelliJ?IDEA?2022.1.1創(chuàng)建java項(xiàng)目的詳細(xì)方法步驟,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07

最新評(píng)論

隆德县| 仁布县| 当阳市| 兴海县| 揭西县| 教育| 同江市| 沭阳县| 济宁市| 正阳县| 新密市| 蒲城县| 西平县| 井陉县| 西畴县| 安康市| 湘潭市| 什邡市| 昆山市| 乐东| 饶平县| 乐平市| 临沂市| 藁城市| 安乡县| 沿河| 万源市| 大丰市| 巴塘县| 宣化县| 阜新| 池州市| 忻州市| 资兴市| 南投县| 广德县| 华坪县| 汤阴县| 荔波县| 财经| 株洲县|