2

私は現在、コードの一部をプレーンJavaコードからOSGi宣言型サービスに変換しています。

元のプレーンJavaコード

new AggregateServiceImpl(
    new ChildServiceImpl1(),
    new ChildServiceImpl2(),
    new ChildServiceImpl3()
);

クラスは次のように宣言されます。

class AggregateServiceImpl implements Service
class ChildServiceImpl1 implements Service
class ChildServiceImpl2 implements Service
class ChildServiceImpl3 implements Service

したがって、すべてのクラスはServiceを実装しますが、Aggregate実装は、必要に応じて子Servicesに延期することができます。

AggregateServiceImpl自体は、他の実装の存在を認識していません。そのコンストラクターは元々次のように宣言されています。

public class AggregateServiceImpl(Service... children)

明確化:インターフェース名「サービス」は一般的に意図されており、OSGiDSまたはサービスの概念を表すことを意図していません。

OSGiへの変換

まず、各実装を独自のバンドルに移動します。次に、コンポーネント(サービス実装)を宣言します。私はたまたまbndを使用しているので、サービスアノテーションを使用します。例えば:

@Component
class ChildServiceImpl1 implements Service

クライアントクラスでは、低レベルのOSGi APIを使用してサービスを検索するか、そのバンドル内のDSを使用してオブジェクトを作成できます。

問題

「サービス」を検索する最良の方法は何ですか?AggregateServiceImplが必要ですが、ChildServiceImplの1つを受け取る可能性があります。

別のサービスタイプを使用するか、コンポーネントの1つ(「isRootService」など)にプロパティを追加して、ServiceReferencesを検索するときにフィルターとして使用するのが最善ですか?

4

2 に答える 2

3

最善の方法は、サービス登録プロパティを使用することです

 @Component
 @Service
 @Property(name = "service.id", value = "<some service unique ID")
 class ChildServiceImpl1 implements Service{...}

特定のサービスを探す場合は、サービスフィルターを使用できます。

bc.getServiceReferences(Service.class.getName(), "(service.id=<some value>)");

または、DSコンポーネントでサービス参照として使用する場合:

@Reference(target = "(service.id=<some value>)", cardinality = ...)
private Service service;
于 2012-09-06T16:50:35.797 に答える
1

AggregateServiceImplが他のバンドルで使用されている唯一のサービスである場合は、それが登録する唯一のサービスである必要があります。

現在示しているコードからは、AggregateServiceImplクラスがServiceまたは実際の実装 に依存しているかどうかを判断できません。

サービスインターフェイスではなく、他の実装に直接依存している場合(現在説明しているように)、集約バンドルは、必要な他の実装クラスを直接作成してから、AggregateServiceImplサービスとして登録する必要があります。

他の実装を他の場所でも使用する必要がある場合は、(提案したように)プロパティを使用して、コンシューマーがそれらを区別できるようにする必要があります。この場合、サービスへの依存関係がないため、DSを使用してアグリゲートを構築することはできません。

于 2012-09-07T13:31:52.270 に答える