38

最初の背景:

私は、OSGI ベースで Apache Felix で実行されるApache Slingに基づく webapp プロトタイプ コードに取り組んでいます。OSGI については、まだほとんどの概念を把握していると思いますが、まだ比較的新しいものです。しかし、私を困惑させているのは、「完全な」依存性注入 (DI) フレームワークを見つけることができなかったことです。Declarative Services (DS) を使用して基本的な DI をうまく採用しました。しかし、私の理解では、DS は参照に使用されています。これをどのように表現すればよいでしょうか? -- OSGI は、サービスとコンポーネントを一緒に登録しました。そのためには問題なく動作しますが、私は個人的にGuiceのような DI フレームワークを使用して、オブジェクト グラフ全体を結び付け、オブジェクトを正しいスコープに配置します (考え@RequestScopedたり、@SessionScoped例えば)。ただし、私が調べた OSGI 固有のフレームワークはどれも、この概念をサポートしていないようです。

私はOSGI ブループリントiPOJOについて読み始めましたが、これらのフレームワークは、完全な DI ソリューションを提供することよりも、OSGI サービスを結び付けることに関心があるようです。私はまだサンプルを作成していないので、私の印象は間違っている可能性があることを認めなければなりません.

Guice の拡張機能としてPeaberryを試してみましたが、ドキュメントを見つけるのが非常に難しく、基本的な DI が機能する一方で、多くの guice-servlet の高度な機能 (フィルター、サーブレットなどへの自動注入) は機能しませんでした。まったく機能しません。

だから、私の質問は次のとおりです。

  1. 宣言型サービスは、Guice や Spring などの「従来の」DI と比べてどうですか? それらは同じ問題を解決しますか、それとも異なる問題を対象としていますか?
  2. 私がこれまで見てきたすべての OSGI 固有のソリューションには、DI のスコープの概念がありません。たとえば、Guice + guice-servlet にはリクエスト スコープの依存関係があり、Web アプリケーションを非常にクリーンで簡単に作成できます。ドキュメントでそれを見逃しただけですか、それともこれらの懸念はこれらのフレームワークのいずれでもカバーされていませんか?
  3. JSR 330とOSGIベースの DI は 2 つの異なる世界ですか? たとえば、iPOJO は独自の注釈を提供しますが、Felix SCR 注釈はまったく別の世界のようです。
  4. OSGI ベースのシステムと DI を構築した経験のある人はいますか? 多分githubのサンプルコードでさえありますか?
  5. Guice と iPOJO のような異なるテクノロジーを一緒に使っている人はいますか?

かなり長い質問で申し訳ありません。

フィードバックは大歓迎です。


アップデート

スコープ インジェクション: スコープ インジェクションは、特定のライフサイクルのオブジェクトを自動的にインジェクトするための便利なメカニズムです。たとえば、一部のコードは、サーブレット フィルターの一部として作成された Hibernate セッション オブジェクトに依存しているとします。依存関係をマークすることにより、コンテナはオブジェクト グラフを自動的に再構築します。たぶん、それにはさまざまなアプローチがありますか?

JSR 330 対 DS : あなたのすべての優れた回答から、これらは 2 つの異なるものであることがわかります。OSGI コンテキストで使用される場合、JSR 330 アノテーションを使用するサード パーティのライブラリとフレームワークをどのように扱うかという問題が生じます。良いアプローチは何ですか?バンドル内で JSR 330 コンテナーを実行していますか?

すべての回答に感謝します。とても役に立ちました。

4

6 に答える 6

28

全体的なアプローチ

Apache Sling で依存性注入を行う最も簡単な方法であり、コードベース全体で使用されている方法は、maven-scr-pluginを使用することです。

Java クラスに注釈を付けてから、ビルド時に SCR プラグインを Maven プラグインまたは Ant タスクとして呼び出すことができます。

たとえば、サーブレットを登録するには、次のようにします。

@Component // signal that it's OSGI-managed
@Service(Servlet.class) // register as a Servlet service
public class SampleServlet implements Servlet {   
   @Reference SlingRepository repository; // get a reference to the repository    
}

具体的な回答

宣言型サービスは、Guice や Spring などの「従来の」DI と比べてどうですか? それらは同じ問題を解決しますか、それとも異なる問題を対象としていますか?

それらは同じ問題を解決します-依存性注入。ただし(以下を参照)、サービスがいつでも表示または非表示になる可能性がある動的システムを考慮して構築されています。

私がこれまで見てきたすべての OSGI 固有のソリューションには、DI のスコープの概念が欠けています。たとえば、Guice + guice-servlet にはリクエスト スコープの依存関係があり、Web アプリケーションを非常にクリーンで簡単に作成できます。ドキュメントでそれを見逃しただけですか、それともこれらの懸念はこれらのフレームワークのいずれでもカバーされていませんか?

SCR の世界では、セッション スコープまたはリクエスト スコープのサービスを追加する方法は見たことがありません。ただし、SCR は一般的なアプローチであり、スコープはより具体的なレイヤーで処理できます。

Sling を使用しているので、Sling には現在のユーザー用に適切に作成された各リクエストの組み込みオブジェクトがあるため、セッション スコープまたはリクエスト スコープのバインディングはほとんど必要ないと思います。

1 つの良い例は、JCR セッションです。正しい権限で自動的に構築され、実際にはリクエストスコープのDAOです。同じことが Sling resourceResolver にも当てはまります。

ユーザーごとの作業が必要な場合、最も簡単な方法は、JCRSessionまたは Slingを受け取るサービスを用意ResourceResolverし、それらを使用して必要な作業を実行することです。結果は、余分な作業をしなくても、現在のユーザーの権限に合わせて自動的に調整されます。

JSR 330 と OSGI ベースの DI は 2 つの異なる世界ですか? たとえば、iPOJO は独自の注釈を提供しますが、Felix SCR 注釈はまったく別の世界のようです。

はい、違います。Spring と Guice はより主流ですが、OSGi サービスはより複雑で、より多くのユース ケースをサポートしていることに注意してください。OSGi バンドル (および暗黙のサービス) では、いつでも自由に利用できます。

これは、利用できなくなったばかりのサービスに依存するコンポーネントがある場合、コンポーネントが非アクティブ化されることを意味します。または、コンポーネントのリスト (たとえば、サーブレットの実装) を受け取り、そのうちの 1 つが非アクティブ化されると、そのことが通知されます。私の知る限り、Spring も Guice も配線が静的であるため、これをサポートしていません。

これは、OSGi が提供する大きな柔軟性です。

OSGI ベースのシステムと DI を構築した経験のある人はいますか? 多分githubのサンプルコードでさえありますか?

Sling Samples SVN リポジトリには多数のサンプルがあります。必要なもののほとんどはそこで見つかるはずです。

Guice と iPOJO のような異なるテクノロジーを一緒に使っている人はいますか?

JSR 330 アノテーションで構成されたフレームワークがある場合、実行時に Guice や Spring などを使用してそれらを構成することは理にかなっています。ただし、Neil Bartlett が指摘したように、これはクロスバンドルでは機能しません。

于 2012-06-23T12:21:03.687 に答える
14

特にJSR330とDSに関して、ロバートの優れた回答にもう少し情報を追加したいと思います。

Declarative Services、Blueprint、iPOJO、およびその他の OSGi「コンポーネント モデル」は、主にOSGi サービスの注入を目的としています。これらは、外部イベント (ネットワークの切断など) やユーザー アクション (バンドルの削除など) への応答を含め、いつでも出入りできるため、通常の依存関係よりも処理が少し難しくなります。したがって、これらすべてのコンポーネント モデルは、純粋な依存性注入フレームワークに追加のライフサイクルレイヤーを提供します。

これが、DS アノテーションが JSR330 アノテーションと異なる主な理由です... JSR330 アノテーションは、ライフサイクルを処理するのに十分なセマンティクスを提供しません。たとえば、彼らは次のことについて何も言いません。

  • いつ依存関係を注入する必要がありますか?
  • 依存関係が現在利用できない場合 (つまり、オプションか必須か)、どうすればよいですか?
  • 使用しているサービスがなくなった場合、どうすればよいですか?
  • サービスのあるインスタンスから別のインスタンスに動的に切り替えることはできますか?
  • 等...

残念なことに、コンポーネント モデルは主にサービス (つまり、バンドル間のリンケージ) に焦点を当てているため、バンドルの依存関係の接続に関しては比較的質素です(ただし、ブループリントはこれに対してある程度のサポートを提供します)。

バンドル内の依存関係を接続するために、既存の DI フレームワークを使用しても問題はありません。たとえば、Guice を使用して一部の Declarative Services コンポーネントの内部部品を接続している顧客がいました。ただし、バンドル内に DI が必要な場合、バンドルが大きすぎて一貫性がない可能性があることを示唆しているため、これを行うことの価値に疑問を抱く傾向があります。

バンドル間でコンポーネントを接続するために、従来の DI フレームワークを使用しないことが非常に重要であることに注意してください。DI フレームワークが別のバンドルからクラスにアクセスする必要がある場合、その別のバンドルはその実装の詳細を公開する必要があります。これにより、OSGi で求めるカプセル化が破られます。

于 2012-06-24T16:49:21.033 に答える
3

AriesBlueprintを使用してアプリケーションを構築した経験があります。OSGiサービスと構成管理サポートに関していくつかの非常に優れた機能があります。

いくつかの優れた例を検索する場合は、すべての配線に設計図を使用するApacheKarafのコードを参照してください。http://svn.apache.org/repos/asf/karaf/を参照してください

また、私のWebサイトにBlueprintとApache Karafのチュートリアルがいくつかあります: http ://www.liquid-reality.de/display/liquid/Karaf+Tutorials

フェリックスが埋め込まれている環境では、Karafの管理機能がないため少し異なりますが、同じバンドルをインストールするだけでうまく機能するはずです。

于 2012-06-23T16:03:21.927 に答える
2

Bndをお勧めします。また、EclipseIDEを特に使用する場合はBndtoolsもお勧めします。これにより、DSをXMLで記述することを避け、代わりに注釈を使用できます。DIには特別なReference注釈があります。これには、サービスの特別なサブセットのみを参照できるフィルターもあります。

于 2012-06-23T08:53:59.107 に答える
1

私は現在の私のプロジェクトに osgi と DI を使用しています。これはSPRING DYNAMIC MODULESの 2 番目のバージョンであるため、gemini 設計図を選択しました。この情報に基づいて、Spring Dynamic Modules in Actionを読むことをお勧めします。この本は、アーキテクチャを構築する方法と、なぜそれが良いのかを理解するのに役立ちます:)

于 2012-06-22T21:44:24.977 に答える
1

ここで同様のアーキテクチャの問題に遭遇しました-ロバートが上記の回答で述べたように:

ユーザーごとの作業が必要な場合、最も簡単な方法は、JCR セッションまたは Sling ResourceResolver を受け取るサービスを用意し、それらを使用して必要な作業を実行することです。結果は、余分な作業をしなくても、現在のユーザーの権限に合わせて自動的に調整されます。

これから (および私が現在コーディングしているもの) から推定すると、1 つのアプローチは、@param resourceResolver任意の@Serviceメソッドに追加して、実行チェーンで使用される適切なリクエストスコープのオブジェクトを渡すことができるようにすることです。

具体的には、相当する JSPから呼び出される/ XXXXService/XXXXDao層があります。したがって、OSGIアノテーションを介してこれらすべてのコンポーネントを管理することで、スタック全体を簡単に接続できます。XXXXServletXXXXViewHelper@Service

ここでの欠点は、インターフェース設計にResourceResolverorパラメータをSessions散らかさなければならないことです。

当初ResourceResolverFactory、DAO レイヤーにインジェクトしようとしたため、ファクトリ経由で自由にセッションに簡単にアクセスできました。ただし、階層内の複数のポイントで、リクエストごとに複数回、セッションと対話しています。これにより、セッション クローズ例外が発生しました。

ResourceResolverすべてのサービスメソッドに渡すことなく、リクエストごとに確実に取得する方法はありますか?

サービスレイヤーでリクエストスコープのインジェクションを使用すると、代わりに ResourceResolver をコンストラクター引数として渡し、代わりにインスタンス変数を使用できます。もちろん、ここでの欠点は、リクエスト スコープとプロトタイプ スコープのサービス コードについて考え、それに応じて分離する必要があることです。

これは、懸念事項をサービス/dao コードに分離し、JCR のやり取りを DAO に残したい場合によくある問題のようですSession。Hibernate と同様に、リクエストごとにレポ操作を実行する方法を簡単に取得できますか?

于 2012-07-25T21:59:29.737 に答える