web-dev-qa-db-ja.com

OSGI環境での依存性注入

最初にいくつかの背景:

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

OSGI blueprintsiPOJO について読み始めましたが、これらのフレームワークは、完全なDIソリューションを提供することよりも、OSGIサービスを一緒に配線することにより関心があるようです。私はまだサンプルを作成していないことを認めなければならないので、私の印象は正しくないかもしれません。

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

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

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

かなり長い質問でごめんなさい。

どんなフィードバックでも大歓迎です。


更新

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

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

私はあなたのすべての答えに感謝します、あなたはとても役に立ちました!

36
ilikeorangutans

全体的なアプローチ

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

Javaクラスに注釈を付け、ビルド時にSvenプラグインを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についても同様です。

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

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

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

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

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

OSGIベースのシステムやDIの構築経験はありますか?たぶんgithubのいくつかのサンプルコードですか?

Sling Samples SVN repository には多数のサンプルがあります。必要なもののほとんどを見つける必要があります。

GuiceとiPOJOのような異なるテクノロジーを一緒に使用している人はいますか、それとも単に奇妙なアイデアですか?

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

28
Robert Munteanu

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

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

これがDS注釈がJSR330の注釈と異なる主な理由です... JSR330の注釈はライフサイクルを処理するための十分なセマンティクスを提供していません。たとえば、次のことについては何も述べていません。

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

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

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

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

14
Neil Bartlett

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

いくつかの素晴らしい例を検索する場合は、すべての配線に青写真を使用するApache Karafのコードをご覧ください。 http://svn.Apache.org/repos/asf/karaf/ を参照してください

私のウェブサイトにはブループリントとApache Karafのチュートリアルもいくつかあります: http://www.liquid-reality.de/display/liquid/Karaf+Tutorials

Felixが組み込まれた環境では、Karafの管理機能がないため少し異なりますが、同じバンドルをインストールするだけで問題なく動作します。

3

私はBndをお勧めします。EclipseIDE sepcially Bndtoolsを使用する場合も同様です。これにより、DSをXMLで記述せずに、注釈を使用することができます。 DIの特別なReferenceアノテーション。これには、サービスの特別なサブセットのみを参照できるフィルターもあります。

2
christian.vogel

ここで同様のアーキテクチャの問題にぶつかります-Robertが彼の回答で前述したように:

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

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

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

ここでの欠点は、ResourceResolverまたはSessionsパラメータを使用してインターフェース設計を散らかす必要があることです。

もともとは、DAOレイヤーにResourceResolverFactoryを挿入しようとしたため、ファクトリーを介して簡単にセッションに簡単にアクセスできました。ただし、階層内の複数のポイントで、リクエストごとに複数回セッションと対話しています。これにより、セッション終了の例外が発生しました。

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

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

これは、Hibernateと同様に、懸念をサービス/ daoコードに分離して、JCRのやり取りをHibernateに任せたい場合によくある問題のようですSessionリポジトリ操作を実行するには?

1
radmike

私は現在のプロジェクトにosgiとDIを使用しています。それは SPRING DYNAMIC MODULES の2番目のバージョンであるため、geminiブループリントを選択しました。この情報に基づいて、お勧めします Spring Dynamic Modules動作中 。この本は、いくつかの部分を理解するのに役立ち、どのようにアーキテクチャを構築するか、なぜそれが良いのかを示します:)

1