SPIの完全な名前はサービスプロバイダーインターフェイスです。これは、サードパーティによって実装または拡張されるJavaによって提供されるAPIのセットであり、フレームワークの拡張および置換コンポーネントを有効にするために使用できます。
Java SPIは、実際には「インターフェースベースのプログラミング+戦略モード+構成ファイル」の組み合わせによって実装される動的な読み込みメカニズムです。
多くの場合、システム設計のさまざまな抽象化には多くの異なる実装がありますが、オブジェクト指向設計では、モジュールに基づいてインターフェイスをプログラミングすることが一般的に推奨され、実装クラスはモジュール間でハードコーディングされていません。特定の実装クラスがコードに含まれると、プラグイン可能な原則に違反するため、実装を置き換える必要がある場合は、コードを変更する必要があります。モジュールのアセンブル時にプログラムで動的に示すことができないことを理解するために、これにはサービス検出メカニズムが必要です。
Java SPIは、そのようなメカニズム、つまりインターフェースのサービス実装を見つけるメカニズムを提供します。IOCの考え方にいくらか似ているのは、アセンブリコントロールをプログラムの外に移動することです。このメカニズムは、モジュール設計で特に重要です。したがって、SPIの中核となるアイデアはデカップリングです。
2使用シナリオ
大まかに言えば、それはに適しています:呼び出し元は、実際の使用ニーズに応じてフレームワークの実装戦略を有効化、拡張、または置き換えます
より一般的な例:
- データベースドライバーロードインターフェイス
は、さまざまなタイプのデータベースをロードするためのクラスロードJDBCドライバーを実装します。 - ログファサードインターフェイス実装クラスの読み込み
SLF4Jは、さまざまなプロバイダーからのログ実装クラスを読み込みます - Spring
Springでは、servlet3.0仕様のServletContainerInitializerの実装、自動型変換Type Conversion SPI(コンバーターSPI、フォーマッターSPI)など、多くのSPIが使用されています。 - Dubbo
Dubboもフレームワークの拡張を実現するために多くのSPIを使用しますが、Javaによって提供されるネイティブSPIをカプセル化し、ユーザーがFilterインターフェースの実装を拡張できるようにします
パブリックインターフェイスSpiService { void test(); } パブリッククラスAspiServiceimplはSpiServiceを実装します{ @Override public void test(){ System.out.println( "AspiServiceimpl-test Method"); } } パブリッククラスBspiServiceimplは、SpiServiceを実装します{ @Override public void test(){ System.out.println( "BspiServiceimpl-test Method"); } }
META-INF / services / com.example.spi.SpiServiceを作成します
com.example.spi.AspiServiceimpl
com.example.spi.BspiServiceimpl
パブリッククラスSpiTest { public static void main(String [] args){ ServiceLoader <SpiService> load = ServiceLoader.load(SpiService.class); for(SpiService s:load){ s.test(); } System.out.println( "***************"); Iterator <SpiService>プロバイダー= Service.providers(SpiService.class); while(providers.hasNext()){ providers.next()。test(); } } }