私はそうのように、複数の実装でサービスを作成しました:適切なサービス実装を選択するにはどうすればよいですか?
@ProviderType
public interface MyService {
public void printMessage();
}
@Component
public class Foo implements MyService {
public void printMessage() {
System.out.println("foo");
}
}
@Component
public class Bar implements MyService {
public void printMessage() {
System.out.println("bar");
}
}
本当の実装は少し複雑明らかにされている(私はちょうどprintMessage
が引数を取る単一の実装をすることはできません!)。サービスのコンシューマは、プロパティに基づいて適切な実装を選択できる必要があります。簡単にするため、実装の名前を使用していると仮定できます。
既存の非のOSGi実装で使用されるファクトリメソッドは次のようなものです:実際の実装は、(それがproperty
パラメータのサブストリングの一致に基づいている)、再び、より複雑である
public MyService getService(String property) {
switch (property) {
case "ham":
return new Foo();
case "spam":
return new Bar();
}
}
。これをOSGiに変換する最も簡単な方法は、このファクトリメソッドをstaticメソッド(MyService
)にして、必要なフィルタ文字列のみを返し、BundleContextを取得することで消費者に手間をかけさせることですサービスungetting:
public class MyConsumer {
private BundleContext context;
@Activate
public void activate(BundleContext context) {
this.context = context;
}
public void doStuff() {
Collection<ServiceReference<MyService>> refs = context.getServiceReferences(MyService.class, MyService.getService("ham"));
ServiceReference<MyService> service = refs.iterator().next();
context.getService(service).printMessage();
context.ungetService(service);
}
は「サービス」を返す「工場」を作成するための良い方法はありますが、消費者がBundleContextsなどに対処することを必要としないのですか?
@Reference(target = "ham")
(私は構文が間違っていることを知っている)私はプロパティに基づいて実装を選択することができますが、唯一の:私はかなり仕事はないだろうカップルのアプローチを見つけたコンパイル時。
ServiceFactory
は、異なるバンドルでサービスの異なるインスタンスを取得できますが、実装を指定することはできません。
実際のユースケースは統合テストツールです。サービスの実装私はさまざまなファイルタイプのテストの正しさについて質問しています。非OSGiバージョンでは、テストで任意の出力ファイルを作成し、工場で適切なサービス実装を選択できます。テスト自体をServiceFactoryを実装するサービスに変換すると、Config Adminで新しいテストインスタンスを作成し、ターゲットを使用して出力タイプを定義することができます。ありがとう – pconley
その場合、タイプを知っているサービスに決定させる必要があります。このような場合、コンシューマはすべてのサービスを繰り返し実行し、ファイルタイプを処理できるかどうかをサービスに問い合わせる必要があります。もしそうなら、検証を行うべきです。非常に慎重でなければ、消費者は可能なすべてのファイルタイプを知っており、新しいファイルタイプを追加するたびにアップデートする必要があるため、ホットスポットになります。 –