サービスプロバイダーインターフェイス(SPI)とアプリケーションプログラミングインターフェイス(API)の違いは何ですか?
より具体的には、Javaライブラリの場合、それらをAPIやSPIにするのは何ですか?
サービスプロバイダーインターフェイス(SPI)とアプリケーションプログラミングインターフェイス(API)の違いは何ですか?
より具体的には、Javaライブラリの場合、それらをAPIやSPIにするのは何ですか?
回答:
言い換えると、APIは特定のクラス/メソッドが何をするかを教えてくれ、SPIは準拠するために何をしなければならないかを教えてくれます。
通常、APIとSPIは別々です。たとえば、JDBC では、Driver
クラスはSPIの一部です。JDBCを単に使用する場合は、JDBCを直接使用する必要はありませんが、JDBCドライバーを実装するすべての人がそのクラスを実装する必要があります。
ただし、重複する場合もあります。インターフェイスはあり、両方の SPIとAPI:あなたはJDBCドライバを使用するときは、定期的にそれを使用し、それは、JDBCドライバの開発者が実装する必要があります。Connection
@SomeAnnotation
いくつかのフレームワークで取得するためにクラスに追加する必要がある場合、SomeAnnotation.class
技術的に拡張または実装していなくても、この注釈クラスはSPIの一部と見なされますか?
より効果的なJavaの第2版:
サービスプロバイダーフレームワークは、複数のサービスプロバイダーがサービスを実装するシステムであり、システムは、クライアントから実装を利用できるようにし、実装から分離します。
サービスプロバイダーフレームワークには3つの重要なコンポーネントがあります。プロバイダーが実装するサービスインターフェイス。システムが実装を登録するために使用するプロバイダー登録API。クライアントにアクセスを提供します。クライアントがサービスのインスタンスを取得するために使用するサービスアクセスAPI。サービスアクセスAPIは通常、プロバイダーを選択するための基準をクライアントが指定することを許可しますが、必須ではありません。そのような仕様がない場合、APIはデフォルト実装のインスタンスを返します。サービスアクセスAPIは、サービスプロバイダーフレームワークの基礎を形成する「柔軟な静的ファクトリー」です。
サービスプロバイダーフレームワークのオプションの4番目のコンポーネントはサービスプロバイダーインターフェイスです。サービスプロバイダーは、プロバイダーがサービス実装のインスタンスを作成するために実装します。サービスプロバイダーインターフェイスがない場合、実装はクラス名で登録され、反映してインスタンス化されます(アイテム53)。JDBCの場合、Connectionはサービスインターフェイスの役割を果たし、DriverManager.registerDriverはプロバイダー登録API、DriverManager.getConnectionはサービスアクセスAPI、Driverはサービスプロバイダーインターフェイスです。
サービスプロバイダーのフレームワークパターンには多数のバリアントがあります。たとえば、サービスアクセスAPIは、アダプターパターンを使用して、プロバイダーに必要なものよりも豊富なサービスインターフェイスを返すことができます[Gamma95、p。139]。次に、サービスプロバイダーインターフェイスとデフォルトプロバイダーを使用した簡単な実装を示します。
// Service provider framework sketch
// Service interface
public interface Service {
... // Service-specific methods go here
}
// Service provider interface
public interface Provider {
Service newService();
}
// Noninstantiable class for service registration and access
public class Services {
private Services() { } // Prevents instantiation (Item 4)
// Maps service names to services
private static final Map<String, Provider> providers =
new ConcurrentHashMap<String, Provider>();
public static final String DEFAULT_PROVIDER_NAME = "<def>";
// Provider registration API
public static void registerDefaultProvider(Provider p) {
registerProvider(DEFAULT_PROVIDER_NAME, p);
}
public static void registerProvider(String name, Provider p){
providers.put(name, p);
}
// Service access API
public static Service newInstance() {
return newInstance(DEFAULT_PROVIDER_NAME);
}
public static Service newInstance(String name) {
Provider p = providers.get(name);
if (p == null)
throw new IllegalArgumentException(
"No provider registered with name: " + name);
return p.newService();
}
}
APIとSPIの違いは、APIがいくつかの具体的な実装を追加で提供するときに発生します。その場合、サービスプロバイダーはいくつかのAPI(SPIと呼ばれる)を実装する必要があります
例はJNDIです。
JNDIは、コンテキスト検索のためのインターフェースといくつかのクラスを提供します。コンテキストを検索するデフォルトの方法は、IntialContextで提供されます。このクラスは、プロバイダー固有の実装に内部的に(NamingManagerを使用して)SPIインターフェースを使用します。
理解を深めるには、以下のJNDIアーキテクチャを参照してください。
APIは、アプリケーションプログラミングインターフェースの略です。APIは、ある種のソフトウェアまたはプラットフォームによって提供されるサービス/機能にアクセスするための手段です。
SPIはService Provider Interfaceの略で、SPIはソフトウェアまたはプラットフォームの動作を挿入、拡張、または変更する方法です。
APIは通常、クライアントがサービスにアクセスするためのターゲットであり、次のプロパティがあります。
-> APIは、特定の動作または出力を実現するためにサービスにアクセスするプログラム的な方法です
-> APIの進化の観点から、クライアントにとって追加はまったく問題ありません
->しかし、クライアントが一度利用したAPIは、クライアントの期待が完全に低下するため、適切な通信がない限り、変更/削除することはできません。
他の部分のSPIはプロバイダーを対象としており、次のプロパティがあります。
-> SPIは、ソフトウェアまたはプラットフォームの動作を拡張/変更する方法です(プログラム可能かプログラム的か)。
-> SPIの削除は問題ではないため、SPIの進化はAPIの進化とは異なります。
-> SPIインターフェイスを追加すると問題が発生し、既存の実装が壊れる可能性があります
詳細については、ここをクリックしてください:サービスプロバイダーインターフェイス
NetBeansのFAQ:SPIとは何ですか?APIとどう違うのですか?
APIは一般的な用語であり、アプリケーションプログラミングインターフェースの頭字語です。これは、ソフトウェアの一部が公開する何か(Javaでは通常、一部のJavaクラス)を意味し、他のソフトウェアと通信できるようにします。
SPIはService Provider Interfaceの略です。これは、ライブラリがアプリケーション(またはAPIライブラリ)によって呼び出されるクラスを提供し、通常アプリケーションが実行できることを変更する状況に固有のAPIになり得るすべてのもののサブセットです。
典型的な例はJavaMailです。そのAPIには2つの側面があります。
- APIサイド—メールクライアントを作成している場合、またはメールボックスを読みたい場合に呼び出す
- ワイヤープロトコルハンドラーを提供してJavaMailがニュースやIMAPサーバーなどの新しい種類のサーバーと通信できるようにする場合のSPI側
APIのユーザーがSPIクラスを表示したり、話したりする必要はほとんどありません。逆も同様です。
NetBeansでは、SPIという用語は、通常、NetBeansが新しいことを実行できるようにするために、モジュールが実行時に挿入できるクラスについて語っています。たとえば、バージョン管理システムを実装するための一般的なSPIがあります。さまざまなモジュールが、CVS、Subversion、Mercurial、およびその他のリビジョン管理システム用のSPIの実装を提供します。ただし、ファイルを処理するコード(API側)は、バージョン管理システムがあるかどうか、またはそれが何であるかを気にする必要はありません。
あまり強調されていないように見える側面が1つありますが、API / SPI分割の存在の背後にある理由を理解するために非常に重要です。
API / SPI分割は、プラットフォームの進化が予想される場合にのみ必要です。APIを記述して、それが将来の改善を必要としないことを"知っている"場合、コードを2つの部分に分割する実際の理由はありません(クリーンなオブジェクトデザインを作成する以外に)。
しかし、これはほとんど当てはまりません。人々は、後方互換性のある方法で、将来の要件とともにAPIを進化させる自由を持つ必要があります。
上記のすべては、他の人が使用および/または拡張するプラットフォームを構築することを想定しており、すべてのクライアントコードを制御できる独自のAPIではなく、したがって必要に応じてリファクタリングできることに注意してください。
よく知られたJavaオブジェクトのいずれかにそれを表示することができますCollection
し、Collections
。
API: Collections
ユーティリティの静的メソッドのセットです。多くの場合、APIオブジェクトを表すクラスfinal
は、(コンパイル時に)クライアントがそのオブジェクトを「実装」できず、静的メソッドの「呼び出し」に依存できるように定義されています。
Collections.emptySet();
すべてのクライアントが「呼び出し」を行うが「実装」を行うわけではないため、JDKの作成者Collections
は、将来のバージョンのJDKでオブジェクトに新しいメソッドを自由に追加できます。たとえ何百万もの使用があったとしても、彼らはそれがどんなクライアントも壊すことができないと確信することができます。
SPI: Collection
誰でも自分のバージョンを実装できることを意味するインターフェースです。したがって、JDKの作成者は、独自のメソッドを記述したすべてのクライアントを破壊するため、新しいメソッドを追加することはできません。Collection
。実装ためです(*)。
通常、追加のメソッドを追加する必要がある場合は、たとえばCollection2
前のインターフェースを拡張する新しいインターフェースを作成する必要があります。次に、SPIクライアントは、SPIの新しいバージョンに移行して追加の方法を実装するか、古いバージョンを使用するかを決定できます。
あなたはすでに要点を見ているかもしれません。両方を組み合わせて1つのクラスにする場合、APIは追加からブロックされます。これabstract class
は、下位互換性に関して将来の進化をブロックするため、優れたJava APIとフレームワークが公開しない理由でもあります。
それでも不明な点がある場合は、上記の詳細を説明しているこのページを確認することをお勧めします。
(*)これはdefault
、インターフェースで定義されたメソッドの概念を導入するJava 1.8までにのみ当てはまることに注意してください。
APIの特定の機能を実装し、サービスルックアップメカニズムを介して利用できるものとして自分自身を登録することにより、SPIスロットをより大きなシステムに組み込むことを想定しています。APIはエンドユーザーアプリケーションコードによって直接使用されますが、SPIコンポーネントを統合する場合があります。カプセル化と直接使用の違いです。
サービスプロバイダーインターフェイスは、すべてのプロバイダーが実装する必要のあるサービスインターフェイスです。既存のプロバイダー実装がどれも機能しない場合は、独自のサービスプロバイダーを作成し(サービスインターフェイスを実装)、どこかに登録する必要があります(Romanによる有用な投稿を参照)。
サービスインターフェースの既存のプロバイダー実装を再利用している場合、基本的には、その特定のプロバイダーのAPIを使用しています。これには、サービスインターフェースのすべてのメソッドと独自のいくつかのパブリックメソッドが含まれています。SPIの外部でプロバイダーAPIのメソッドを使用している場合は、プロバイダー固有の機能を使用しています。
Javaの世界では、さまざまなテクノロジーがモジュール化されており、アプリケーションサーバーに「プラグイン可能」です。次に違いがあります
そのようなテクノロジーの2つの例は、JTA(トランザクションマネージャー)とJCA(JMSまたはデータベース用のアダプター)です。しかし、他にもあります。
このようなプラガブルテクノロジの実装者は、アプリにプラガブルになるようにSPIを実装する必要があります。サーバー、およびエンドユーザーアプリケーションで使用されるAPIを提供します。JCAの例は、SPIの一部であるManagedConnectionインターフェース、およびエンドユーザーAPIの一部であるConnectionです。