ホームページ >Java >&#&チュートリアル >SpringBootのSPIメカニズムを実装する方法

SpringBootのSPIメカニズムを実装する方法

WBOY
WBOY転載
2023-05-16 09:10:11962ブラウズ

    はじめに

    SPI (Service Provider Interface) は、JDK に組み込まれたサービス検出メカニズムであり、フレームワークの拡張機能やコンポーネントの置き換えを可能にするために使用できます。 Dubbo、Spring、Common-Logging、JDBC などのフレームワークでの開発では、SPI メカニズムを使用して、同じインターフェイスの異なる実装を異なるユーザーに提供し、フレームワークのスケーラビリティを向上させます。

    Java SPI 実装

    Java の組み込み SPI は、java.util.ServiceLoader クラスを使用して、classPath および META-INF/services/ 内のインターフェイスの完全修飾名で指定されたファイルを解析します。 jar パッケージのディレクトリを指定し、ファイル内で指定されたインターフェイス実装クラスをロードして呼び出しを完了します。

    例の説明

    動的インターフェイスの作成

    public interface VedioSPI
    {
        void call();
    }

    実装クラス 1

    public class Mp3Vedio implements VedioSPI
    {
        @Override
        public void call()
        {
            System.out.println("this is mp3 call");
        }
    }

    実装クラス 2

    public class Mp4Vedio implements VedioSPI
    {
        @Override
        public void call()
        {
           System.out.println("this is mp4 call");
        }
    }

    ソース ディレクトリ内プロジェクト 新しい META-INF/services/ ディレクトリに com.skywares.fw.juc.spi.VedioSPI ファイルを作成します。

    SpringBootのSPIメカニズムを実装する方法

    関連テスト

    public class VedioSPITest
    {
        public static void main(String[] args)
        {
            ServiceLoader<VedioSPI> serviceLoader =ServiceLoader.load(VedioSPI.class);
            serviceLoader.forEach(t->{
                t.call();
            });
        }
    }

    説明: Java は、ServiceLoader を介して spi を実装し、サービスによって提供されるツール クラスを見つけます。

    実行結果

    SpringBootのSPIメカニズムを実装する方法

    ソースコード分析

    上記は、Java の組み込み SPI 関数を実装する簡単な例にすぎません。実装原理としては、ServiceLoader はサービス提供インターフェースを見つけるための組み込み Java ツールクラスであり、load() メソッドを呼び出してサービス提供インターフェースを検索し、最後にサービス提供インターフェースの実装クラスを 1 つずつトラバースしてアクセスします。 。

    SpringBootのSPIメカニズムを実装する方法

    ソース コードから見つけることができます:

    • ServiceLoader クラス自体は Iterable インターフェイスを実装し、次の iterator メソッドを実装します。 it. iterator メソッド 内部クラス LazyIterator のメソッドが実装で呼び出されます. サービス プロバイダー インターフェイス ファイルを解析した後、最終結果が Iterator に配置されて返されます. サービス プロバイダー インターフェイス実装クラスへの直接アクセスはサポートされていません.

    • すべてのサービス プロバイダー インターフェイスに対応するファイルは、META-INF/services/ ディレクトリに配置され、最後のタイプにより、PREFIX ディレクトリを変更できないことが決定されます。

    Java が提供する SPI メカニズムのアイデアは非常に優れていますが、相応の欠点もあります。詳細は次のとおりです。

    • Java の組み込みメソッドはトラバーサルを通じてのみ取得できます

    • サービス プロバイダー インターフェイスは META に配置する必要があります-INF/サービス/ コンテンツの下。

    Java の SPI に存在する問題を考慮して、Spring の SPI メカニズムは SPI の考え方に従いながら、それを拡張し、最適化しています。

    Spring SPI

    Spring SPI は、Java SPI の設計思想に従っています。Spring は、spring.factories メソッドを使用して SPI メカニズムを実装し、Spring ソースを変更せずに Spring フレームワークを提供できます。コード、スケーラビリティ。

    Spring の例

    定義インターフェイス

    public interface DataBaseSPI
    {
       void getConnection();
    }

    関連実装

    #DB2实现
    public class DB2DataBase implements DataBaseSPI
    {
        @Override
        public void getConnection()
        {
            System.out.println("this database is db2");
        }
    }
    #Mysql实现
    public class MysqlDataBase implements DataBaseSPI
    {
        @Override
        public void getConnection()
        {
           System.out.println("this is mysql database");
        }
    }

    1. プロジェクトの META-INF ディレクトリに、 spring.factories ファイルを追加します。

    SpringBootのSPIメカニズムを実装する方法

    2. 関連するインターフェイス情報を入力します。内容は次のとおりです。

    com.skywares.fw.juc.springspi.DataBaseSPI = com.skywares.fw .juc.springspi.DB2DataBase、com.skywares.fw.juc.springspi.MysqlDataBase

    説明 複数の実装はカンマで区切られます。

    関連テストクラス

    public class SpringSPITest
    {
        public static void main(String[] args)
        {
             List<DataBaseSPI> dataBaseSPIs =SpringFactoriesLoader.loadFactories(DataBaseSPI.class, 
                     Thread.currentThread().getContextClassLoader());
             for(DataBaseSPI datBaseSPI:dataBaseSPIs){
                datBaseSPI.getConnection();
             }
        }
    }

    出力結果

    SpringBootのSPIメカニズムを実装する方法

    この例から、Spring が spring.factories を使用して SPI と Java を実装していることがわかります。実装 SPI は非常に似ていますが、Java の spi に対する Spring の spi メソッドの最適化は次のとおりです。

    • Java SPI は、設定ファイルに対応するインターフェイスを提供するサービスであり、設定ファイル現在のインターフェイスのすべての実装クラスを保存します。複数のサービス プロバイダー インターフェイスは複数の設定ファイルに対応し、すべての設定はサービス ディレクトリにあります。

    • Spring Factory SPI は spring.factories 設定ファイルです。複数のインターフェイスと対応する実装クラスは、キーとしてインターフェイスの完全修飾名、値として実装クラスを使用して設定されます。複数の実装クラスはカンマで区切られます。設定ファイルは spring.factories の 1 つだけです。

    では、spring.factories をロードすることで、Spring はどのように SpI を実装するのでしょうか? ソース コードを通じてさらに分析できます。

    ソース コード分析

    SpringBootのSPIメカニズムを実装する方法

    説明:loadFactoryNames は、spring.factories ファイル内の指定されたインターフェイスの実装クラスの完全修飾名を解析します。以下のとおりであります: #### ########

    説明: すべての jar パッケージ内の META-INF/spring.factories のファイル パスを取得し、それを列挙値として返します。 spring.factories ファイルのパスをたどり、1 つずつロードおよび解析し、factoryClass 型の実装クラス名を統合し、実装クラスの完全なクラス名を取得して、クラスのインスタンス操作を実行します。関連するソース コードは次のとおりです。

    SpringBootのSPIメカニズムを実装する方法

    注: インスタンス化は、リフレクションを通じて対応する初期化を実装します。

    以上がSpringBootのSPIメカニズムを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。