1. 程式人生 > >SPI 機制-外掛化擴充套件功能

SPI 機制-外掛化擴充套件功能

SPI(Service Provider Interfaces),中文直譯服務提供者介面,一種服務發現機制。可能很多人都不太熟悉這個機制,但是平常或多或少都用到了這個機制,比如我們使用 JDBC 連線操作資料庫的時候。

SPI 主要適用於功能擴充套件的場景,如一些框架提供某一部分功能可以由第三方開發人員擴充套件,滿足其自身業務需求。

假設我們在公司內實現了一個統一登陸框架,框架內部僅僅提供使用者名稱/密碼登陸方式。後來 A 部門想使用該框架,但是他們想增加微信登陸授權。正常情況下,我們可以改動登陸框架程式碼,增加微信登陸實現方式。如果後面又增加 QQ 登陸,淘寶登陸那?也只能不斷相應的實現。

SPI 實現方式

這種情況如果使用 SPI,可以在不用改動框架程式碼前提下,增加新的登陸實現方式。下面用程式碼演示如何使用 SPI。

定義介面

首先我們新建一個 maven 專案 oauth-api,在這個專案建立一個公共介面。

public interface OauthLoginService {
    void login();
}

第三方實現該介面

再新建一個 maven 專案 wechat-oauth ,引入上面 oauth-api 依賴

public class WechatLoginService implements OauthLoginService {
    @Override
    public void login() {
        System.out.println("使用微信登陸授權");
    }
}

定義配置檔案

SPI 需要將介面實現定義在配置檔案中,檔名為介面全名稱,如 com.andyxh.OauthLoginService,配置檔案需放在 resources\META-INF\services 資料夾下。檔案內容如下:

com.another.WechatLoginService

載入介面實現類

新建 maven 專案 oauth-login,在這個專案中引入 wechat-oauthoauth-api 依賴。SPI 核心將會使用 java.util.ServiceLoader讀取上面上面定義配置檔案,載入所有服務實現類。使用程式碼如下:


ServiceLoader<OauthLoginService> serviceLoader=ServiceLoader.load(OauthLoginService.class);
serviceLoader.forEach(OauthLoginService::login);

列印結果:

使用微信登陸授權

SPI 實際應用

上面說過 JDBC 中使用到 SPI 進位制。 JDK 定義標準資料庫介面,相應的資料庫廠商實現這類介面。以 mysql-connector-javal 為例。

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>

mysql jar 包 META-INF/services 中存在java.sql.Driver 檔案,這個檔案定義了實現類。

com.mysql.cj.jdbc.Driver

可以看到 java.sql.Driver 是標準 SPI 介面,而 com.mysql.cj.jdbc.Driver 是 mysql 標準實現介面。

何時載入 java.sql.Driver

我們將會使用 DriverManager.getConnection 獲取相應資料庫連線。這個類內部存在一個靜態程式碼塊,將會使用 ServiceLoader 載入實現類。

    static {
        loadInitialDrivers();
        println("JDBC DriverManager initialized");
    }

 private static void loadInitialDrivers() {
        ....
     ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);  
     Iterator<Driver> driversIterator = loadedDrivers.iterator();  
     try{  
         while(driversIterator.hasNext()) {  
         driversIterator.next();  
     }  
     } catch(Throwable t) {  
         // Do nothing  
     }  
         return null;  
     }
    ....
    }

Java SPI 存在問題

ServiceLoader 一次性將會例項化所有實現,但是如果沒有某一擴充套件初始化耗時很久,但是卻不需要立刻使用,就會非常浪費資源。

基於這個問題, Dubbo SPI 機制改進 Java SPI 的不足,做到按需載入並且增加 ioc 與 aop 的功能,下篇文章可以在具體聊聊,敬請期待。

相關推薦

SPI 機制-外掛擴充套件功能

SPI(Service Provider Interfaces),中文直譯服務提供者介面,一種服務發現機制。可能很多人都不太熟悉這個機制,但是平常或多或少都用到了這個機制,比如我們使用 JDBC 連線操作資料庫的時候。 SPI 主要適用於功能擴充套件的場景,如一些框架提供某一部分功能可以由第三方開發人員擴充套

Dubbo 的 SPI 機制(三)(Extension 擴充套件點補充)

相關部落格: Dubbo的SPI機制(一)(Java的SPI) Dubbo的SPI機制(二)(Dubbo優化後的SPI實現)   Dubbo 的 Extension 主要是基於 SPI 思想實現的自己的 SPI 的工具。  在上一篇部落格(Dubbo的SP

Android外掛原理解析——Hook機制之Binder Hook

Android系統通過Binder機制給應用程式提供了一系列的系統服務,諸如ActivityManagerService,ClipboardManager, AudioManager等;這些廣泛存在系統服務給應用程式提供了諸如任務管理,音訊,視訊等異常強大的功能。 外掛

小白也能看懂的外掛DroidPlugin原理(二)-- 反射機制和Hook入門

  前言:在上一篇博文《小白也能看懂的外掛化DroidPlugin原理(一)-- 動態代理》中詳細介紹了 DroidPlugin 原理中涉及到的動態代理模式,看完上篇博文後你就會發現原來動態代理真的非常簡單,只不過就是實現一個 InvocationHandler 介面重寫一

Android外掛原理解析--外掛載入機制

上文 Activity生命週期管理 中我們地完成了『啟動沒有在AndroidManifest.xml中顯式宣告的Activity』的任務;通過Hook AMS和攔截ActivityThread中H類對於元件排程我們成功地繞過了AndroidMAnifest.xml的限制。但是

Android 外掛原理解析——外掛載入機制

上文 Activity生命週期管理 中我們地完成了『啟動沒有在AndroidManifest.xml中顯式宣告的Activity』的任務;通過Hook AMS和攔截ActivityThread中H類對於元件排程我們成功地繞過了AndroidMAnifest.xml的限

Android 外掛之Hook機制

Android Hook簡介 什麼是Hook Hook 英文翻譯過來就是「鉤子」的意思,就是在程式執行的過程中去擷取其中的資訊。Android 作業系統中系統維護著自己的一套事件分發機制,那麼Hook就是在事件傳送到終點前截獲並監控事件的傳輸。其原理示意圖如

Android外掛原理解析——Hook機制之動態代理

使用代理機制進行API Hook進而達到方法增強是框架的常用手段,比如J2EE框架Spring通過動態代理優雅地實現了AOP程式設計,極大地提升了Web開發效率;同樣,外掛框架也廣泛使用了代理機制來增強系統API從而達到外掛化的目的。本文將帶你瞭解基於動態代理的Hook機制。 閱讀本文之前,可以先clo

Android外掛系列第(四)篇---外掛載入機制兩種方案

一、相關概念 1.1、為什麼需要動態載入 這個問題,前面已經介紹過,如下 Android系統使用了ClassLoader機制來進行Activity等元件的載入;apk被安裝之後,APK檔案的程式碼以及資源會被系統存放在固定的目錄(比如/d

深入了解java虛擬機---類加載機制----初始階段

機制 類加載機制 初始 定義 lan tro 過程 懶加載 類加載 準備階段是給變量賦系統的初始值。而初始化階段就是給變量賦程序員自己設的值 初始化階段是<clinit>()方法的執行過程。過程如下 1.編輯器收集所有的賦值動作和靜態塊合並形成<cli

Dubbo的SPI機制(6)——AOP

cached 函數 bsp load 包裝 aop loader 緩存 mage 在 ExtensionLoader 類的loadFile方法中有下圖的這段代碼: 類如現在這個ExtensionLoader中的type 是Protocol.class,也就是SPI接口

Java SPI機制

ffffff type iterator path args gin int pub .html Service Provider Interfaces 服務提供發現,動態替換發現的機制 示例: 一個接口:public interface Calc { Logge

Asp.Net Core中利用Seq組件展示結構日誌功能

eve 發布 哪裏 HA 快速 inf ron void 級別 在一次.Net Core小項目的開發中,掌握的不夠深入,對日誌記錄並沒有好好利用,以至於一出現異常問題,都得跑動服務器上查看,那時一度懷疑自己肯定沒學好,不然這一塊日誌不可能需要自己扒服務器日誌來查看,果然,很

WordCount的基本功能擴充套件功能(兩人組隊完成)

合作者:201631062118,201631062217 專案gitee連結:https://gitee.com/suiran90/wc/ (注:由於gitee操作不熟練,此次我們兩人程式碼上傳時出現問題,商議為由我上傳,相關操作正在學習) 本次作業連結地址:https://edu.cnblogs.com/

滴滴開源Android外掛框架VirtualAPK原理分析

概述 Activity 支援 Hook ActivityManagerService Hook Instrumentation 啟動外掛Acti

開發版速達擴充套件功能---業務單據明細表格資料匯入

原版速達軟體在單據明細匯入的時候,只能提供文字方式匯入,既不友好,也不方便,而且列頭只能固化,匯入的資料列也是很有限;而開發版速達則提供了當代流行的Excel匯入模式,匯入的列和列名都可以由使用者自己定製,下面聚為大家詳細講解下開發版業務單據明細匯入的方式,以下以銷售開單為講解,其他單據都是類似: 1.先開

關於360外掛框架Replugin豎屏修改為橫屏解決方案

預備工作 去GitHub搜尋replugin工程,下載replugin原始碼,解壓如下,游標選中的部分是我們要修改的地方。 1.1.20 為什麼要修改Gradle 因為Replugin原生的預設生成activity坑位都是豎屏的,而車機是橫屏的,導致外掛activity 實際效果與預期

WordCount結對作業——實現擴充套件功能

合作者學號:201631081309 201631062307 作業連結 碼雲地址 一:實現的功能。 WordCount是一個簡單的小程式,實現了一下幾項基本功能。 - 統計字元數 - 統計單詞數 - 統計文字行 以及擴充套件功能 - 統計註釋行、程式碼行、以及空行 - 遞迴處理目錄下符合條件的檔案 -

[Songqw.Net 基礎]WPF外掛中同步Style

原文: [Songqw.Net 基礎]WPF外掛化中同步Style 之前將WPF Client中的各個頁面拆分為一個個外掛,進行開發,介面是原生的還好說,一旦統一樣式,每個外掛模組都來一份資原始檔,就不合理了嘍. 先從Style入手,做一下同步. 思路是直接將Style拆離出來

[Songqw.Net 基礎]WPF實現簡單的外掛開發

原文: [Songqw.Net 基礎]WPF實現簡單的外掛化開發 接著上一篇部落格, 那裡實現了簡單的控制檯載入外掛,在這裡通過WPF實現,做個備份. WPF控制元件空間經常會與WinFrom混淆,要記得WPF控制元件是引用 using System.Windows.Co