2016-08-17 2 views
1

私はそうのように、複数の実装でサービスを作成しました:適切なサービス実装を選択するにはどうすればよいですか?

@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は、異なるバンドルでサービスの異なるインスタンスを取得できますが、実装を指定することはできません。

答えて

2

サービスのアイデアは、消費者が非常に再利用不可能になるため、消費者は選択しないことです。あなたがそのコントロールを消費者に移すと、一般に脆弱なシステムになります。消費者は登録されているものを使用するべきです。

アンチパターンの1つは、サービスの実装を非表示にして、コンシューマに特定の実装を必要とすることです。これがユースケースの場合、実装は公開されており、独自のサービスタイプにするだけです。それはもちろん、共通のMyServiceタイプとして登録することができます。もちろん、複数のタイプで登録することもできます。

使用する外部の選択基準がある場合、例:プリンタを選択して、ユーザーに決定させたい場合は、すべてを取得してユーザーに表示します。サービスIDを使用すると、正しいIDを使用できます。

使用するサービスを設定する必要がある場合は、@Reference(target="(selection.criterium=foo)")を使用する必要があります。 Configuration Administratorでこの選択を無効にすることができます。これはtargetsで説明されています。基本的には、参照名の後に必要なフィルタに.targetを続けてプロパティを設定します。

+0

実際のユースケースは統合テストツールです。サービスの実装私はさまざまなファイルタイプのテストの正しさについて質問しています。非OSGiバージョンでは、テストで任意の出力ファイルを作成し、工場で適切なサービス実装を選択できます。テスト自体をServiceFactoryを実装するサービスに変換すると、Config Adminで新しいテストインスタンスを作成し、ターゲットを使用して出力タイプを定義することができます。ありがとう – pconley

+0

その場合、タイプを知っているサービスに決定させる必要があります。このような場合、コンシューマはすべてのサービスを繰り返し実行し、ファイルタイプを処理できるかどうかをサービスに問い合わせる必要があります。もしそうなら、検証を行うべきです。非常に慎重でなければ、消費者は可能なすべてのファイルタイプを知っており、新しいファイルタイプを追加するたびにアップデートする必要があるため、ホットスポットになります。 –

関連する問題