中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java怎么用SPI實現解耦

發布時間:2023-04-07 17:08:32 來源:億速云 閱讀:202 作者:iii 欄目:開發技術

這篇“Java怎么用SPI實現解耦”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Java怎么用SPI實現解耦”文章吧。

概述

SPI的全稱是服務提供接口,可以用其來啟動框架的擴展和替換組件。

其本質是利用 接口實現+策略模式+配置文件來實現對實現類的動態加載。

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

(1)規定在 classPath 的 META-INF/services/ 下,創建該接口的全名稱文件

(2)在該文件中,寫入該接口實現類全稱(路徑+文件名),多個實現類的話,分行寫。

(3)用的2時候,使用 java.util.ServiceLoader 的 load(Interface.class),獲取到實現類,就可以使用了。

值得注意的是,接口實現類必須有一個不帶參數的構造方法。

實現案例

在本應用中,存在兩個模塊,分別為A模塊和B模塊,這兩個模塊中,A模塊是主模塊,B是從模塊,B模塊是依賴A模塊的。但是在目前有一個類,該類中實現在B模塊中,A模塊需要調用這個類的函數,而模塊不能再依賴B模塊,此時需要進行解耦。在本實現中,利用SPI的方式進行解耦實現。具體實現方案為:

(1)在A模塊新建一個接口:MyLogAppender,具體實現為:

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

public interface MyLogAppender {

    /**
     * 獲取實現的appender
     * @return  返回新建的appender對象
     * */
    Appender getAppender();
}

這個接口很簡單,只是返回一個appender的對象。對于對象的實際操作,在接口的實現中進行操作。

(2)在B模塊添加對這個接口的實現,具體的操作為:

/**
 * @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("發布日志時,廣播失敗");
        }
    }

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

在該接口的申明和接口的實現中,存在一些小的技巧的實現。在接口中,只聲明一個類的獲取,并沒有實現具體的方法。在實現類中,對這個類進行實例化,new一個新的類并返回,此時用戶根據這個get方法就可以拿到這個實現類,然后進行實現類的一些操作。這樣寫可以帶來兩個好處: i. 代碼更簡潔,接口的代碼簡單易懂 ii. 可以在實現類的構造方法中注入一些參數,當用戶使用時,直接在get方法里面注入即可。

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

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

其文件中的內容為:com.alibaba.lattice2.epoch.util.MeshLogAppender

其原理是,當用戶使用接口時,會掃描項目下的所有文件,查找文件名為com.alibaba.halo.sandbox.app.util.MyLogAppender,然后根據其內容來查找到相關的實現類

(4)在A,可以直接使用接口來進行調用,具體實現如下:

				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);
        }

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

優勢和不足

優點:可以實現代碼的解耦

缺點:存在多個實現類的話,無法根據某個參數或者標志位獲取實例,只能通過遍歷獲取,沒有實現所謂的懶加載

以上就是關于“Java怎么用SPI實現解耦”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

武威市| 佳木斯市| 黑山县| 会东县| 靖州| 紫金县| 衡东县| 木兰县| 双鸭山市| 财经| 金乡县| 陈巴尔虎旗| 正镶白旗| 富宁县| 绍兴县| 临洮县| 内乡县| 延川县| 安庆市| 凯里市| 芮城县| 霍林郭勒市| 兰考县| 夹江县| 墨竹工卡县| 昔阳县| 嘉鱼县| 呼图壁县| 建宁县| 会同县| 南乐县| 江阴市| 揭西县| 宜丰县| 蚌埠市| 卓资县| 米脂县| 桑植县| 阿尔山市| 罗平县| 讷河市|