JavaにおけるSPIメカニズム
3030 ワード
SPIのフルネームは:Service Provider Interfaceで、多くの開発者はこれがメーカーやプラグイン向けであるため、よく知らないかもしれません.Java.util.ServiceLoaderのドキュメントでは比較的詳細に説明されています.
簡単にまとめて Java SPI メカニズムの思想.私たちのシステムの抽象的な各モジュールには、ログモジュールのスキーム、xml解析モジュール、jdbcモジュールのスキームなど、多くの異なる実装スキームがあります.オブジェクト向けの設計では,モジュール間でインタフェースに基づいてプログラミングを推奨し,モジュール間で実装クラスをハードコーディングしない.
コードに具体的な実装クラスが含まれると、プラグイン可能な原則に違反し、実装を置き換える必要がある場合は、コードを修正する必要があります.モジュールの組み立て時にプログラムに動的に示さないようにするには,サービス発見メカニズムが必要である.
Java SPIは,あるインタフェースのためにサービス実装を探すメカニズムを提供する.IOCの考えに似ているのは、組み立ての制御権をプログラムの外に移すことであり、モジュール化設計においてこのメカニズムが特に重要である.
Java SPI の具体的な約束は、サービスのプロバイダが、サービスインタフェースの実装を提供した後、jarパッケージのMETA-INF/services/ディレクトリに、サービスインタフェースと命名されたファイルを同時に作成することである.このファイルには,このサービスインタフェースを実現する具体的な実装クラスがある.
外部プログラムがこのモジュールを組み立てると、jarパッケージMETA-INF/services/のプロファイルから具体的な実装クラス名を見つけ、インスタンス化をロードしてモジュールの注入を完了することができます.
このような約束に基づいて、コードで作成する必要がなく、サービスインタフェースの実装クラスをよく見つけることができます.jdkは、java.util.ServiceLoaderというサービス実装検索のツールクラスを提供します.
1.common-logging
apacheが最初に提供したログのフェースインタフェース.インタフェースのみで、実装されていません.具体的な案は各プロバイダによって実現され、発見ログプロバイダはMETA-INF/services/org.apache.commons.logging.LogFactoryプロファイルをスキャンし、そのファイルの内容を読み取ることによってログ提工商実現類を見つける.
ログインプリメンテーションにこのファイルが含まれており、ログファクトリインタフェースのインプリメンテーションクラスをファイルに作成すればよい.Javaテクノロジースタックの微信公衆番号に注目し、バックグラウンドでキーワード:Javaに返信し、スタック長が整理したJavaテクノロジーの干物をより多く取得することができます.
2.jdbc
jdbc 4.0以前は、開発者はClass.forName(「xxx」)に基づいてドライバをロードする必要があり、jdbc 4もspiのメカニズムに基づいてドライバプロバイダを発見し、META-INF/services/java.sql.Driverファイルで実装クラスを指定することでドライバプロバイダを暴露することができます.
コンテンツ管理システムには検索モジュールがあります.インタフェースに基づいてプログラミングされています.検索の実装は、ファイルシステムベースの検索であるか、データベースベースの検索であるかのいずれかです.
インタフェースの定義は次のとおりです.
A社はファイルシステム検索方式でSearchインタフェースを実現し、B社はデータベースシステム方式でSearchインタフェースを実現した.
A社が実現したクラス:com.A.spi.impl.FileSearch B社が実現したクラス:com.B.spi.impl.DatabaseSearch
では、A社が実装jarパッケージをリリースする場合は、jarパッケージのMETA-INF/services/my.xyz.spi.Searchファイルに次のように書きます.
では、B社が実装jarパッケージをリリースする場合は、jarパッケージのMETA-INF/services/my.xyz.spi.Searchファイルに次のように書きます.
次はSPIテストコードです.
簡単にまとめて Java SPI メカニズムの思想.私たちのシステムの抽象的な各モジュールには、ログモジュールのスキーム、xml解析モジュール、jdbcモジュールのスキームなど、多くの異なる実装スキームがあります.オブジェクト向けの設計では,モジュール間でインタフェースに基づいてプログラミングを推奨し,モジュール間で実装クラスをハードコーディングしない.
コードに具体的な実装クラスが含まれると、プラグイン可能な原則に違反し、実装を置き換える必要がある場合は、コードを修正する必要があります.モジュールの組み立て時にプログラムに動的に示さないようにするには,サービス発見メカニズムが必要である.
Java SPIは,あるインタフェースのためにサービス実装を探すメカニズムを提供する.IOCの考えに似ているのは、組み立ての制御権をプログラムの外に移すことであり、モジュール化設計においてこのメカニズムが特に重要である.
Java SPI の具体的な約束は、サービスのプロバイダが、サービスインタフェースの実装を提供した後、jarパッケージのMETA-INF/services/ディレクトリに、サービスインタフェースと命名されたファイルを同時に作成することである.このファイルには,このサービスインタフェースを実現する具体的な実装クラスがある.
外部プログラムがこのモジュールを組み立てると、jarパッケージMETA-INF/services/のプロファイルから具体的な実装クラス名を見つけ、インスタンス化をロードしてモジュールの注入を完了することができます.
このような約束に基づいて、コードで作成する必要がなく、サービスインタフェースの実装クラスをよく見つけることができます.jdkは、java.util.ServiceLoaderというサービス実装検索のツールクラスを提供します.
1.common-logging
apacheが最初に提供したログのフェースインタフェース.インタフェースのみで、実装されていません.具体的な案は各プロバイダによって実現され、発見ログプロバイダはMETA-INF/services/org.apache.commons.logging.LogFactoryプロファイルをスキャンし、そのファイルの内容を読み取ることによってログ提工商実現類を見つける.
ログインプリメンテーションにこのファイルが含まれており、ログファクトリインタフェースのインプリメンテーションクラスをファイルに作成すればよい.Javaテクノロジースタックの微信公衆番号に注目し、バックグラウンドでキーワード:Javaに返信し、スタック長が整理したJavaテクノロジーの干物をより多く取得することができます.
2.jdbc
jdbc 4.0以前は、開発者はClass.forName(「xxx」)に基づいてドライバをロードする必要があり、jdbc 4もspiのメカニズムに基づいてドライバプロバイダを発見し、META-INF/services/java.sql.Driverファイルで実装クラスを指定することでドライバプロバイダを暴露することができます.
コンテンツ管理システムには検索モジュールがあります.インタフェースに基づいてプログラミングされています.検索の実装は、ファイルシステムベースの検索であるか、データベースベースの検索であるかのいずれかです.
インタフェースの定義は次のとおりです.
package my.xyz.spi;
import java.util.List;
public interface Search {
public List serch(String keyword);
}
A社はファイルシステム検索方式でSearchインタフェースを実現し、B社はデータベースシステム方式でSearchインタフェースを実現した.
では、A社が実装jarパッケージをリリースする場合は、jarパッケージのMETA-INF/services/my.xyz.spi.Searchファイルに次のように書きます.
com.A.spi.impl.FileSearch
では、B社が実装jarパッケージをリリースする場合は、jarパッケージのMETA-INF/services/my.xyz.spi.Searchファイルに次のように書きます.
com.B.spi.impl.DatabaseSearch
次はSPIテストコードです.
package com.xyz.factory;
import java.util.Iterator;
import java.util.ServiceLoader;
import my.xyz.spi.Search;
public class SearchFactory {
private SearchFactory() {
}
public static Search newSearch() {
Search search = null;
ServiceLoader serviceLoader = ServiceLoader.load(Search.class);
Iterator searchs = serviceLoader.iterator();
if (searchs.hasNext()) {
search = searchs.next();
}
return search;
}
}