OSGiは、(任意のバンドルからエクスポートされた)単一のパッケージをワイヤリングするImport-Package
と、特定の名前付きバンドルのエクスポートにワイヤリングするRequire-Bundle
を介して依存関係を決定できるようにします。
グリーンフィールドOSGiアプリケーションを構築する場合、依存関係を表すためにどのアプローチを使用すればよいですか?ほとんどのバンドルは内部にありますが、外部(オープンソース)バンドルにはいくつかの依存関係があります。
私はRequire-Bundle
はEclipseのものだと信じています(これにより、OSGi仕様でEclipseに対応できるようになりました)。 「純粋な」OSGiの方法は、Import-Package
を使用することです。これは、パッケージを提供するバンドルからパッケージを明確に分離するためです。必要な機能への依存関係(Java特定のパッケージの特定のバージョンで提供されるAPI))を宣言する必要があります(その機能の提供元(重要ではないはず))ではありません。これにより、バンドルの構成がより柔軟になります。
JavaScriptの類推:これは、Webエージェントが特定のAPIをサポートしているかどうかを検出するのではなく、ユーザーエージェント文字列がブラウザの種類を示していることから推測するようなものです。
OSGiアライアンスのPeter Kriensは、これについて OSGiブログ でさらに詳しく述べています。
おそらく、Require-Bundle
を使用する必要がある唯一のケースは、分割パッケージがある場合、つまり、複数のバンドルにまたがるパッケージである場合です。もちろん分割パッケージはお勧めしません。
必須バンドルよりもインポートパッケージを優先します。
バンドルが必要:
インポートパッケージ:
Import-Packageを使用すると結合が緩くなるため、推奨されるはずです。私が所有していないパッケージ(slf4jなど)への依存関係を宣言するときに使用し、必要に応じて実装を入れ替えることができます。依存関係が自分のバンドルなど、自分で制御できるものである場合は、いずれにせよ重要な変更は自分自身で行われるため、Require-Bundleを使用します。
Import-Packageは避けてください。パッケージはバンドル間に多対多の関係を提供するため、検出および回避が困難な依存サイクルが発生しやすくなります。
一方、Require-Bundleは単一のバンドルを参照し、簡単なビルド時チェックによって依存関係グラフをサイクルから保護します。 Require-Bundleを使用すると、分離された下位レベルの抽象化を使用してレイヤードアーキテクチャを構築することがはるかに簡単になります。
以前に述べたように、既存のクライアントのMANIFEST.MFを変更せずに、あるバンドルから別のバンドルにパッケージを移動できるため、Import-Package
の方が良いはずです。
だが...
Eclipseを使用してバンドルを開発している場合は、Require-Bundle
を使用する実用的な理由があります。
Eclipseは解決の単位としてパッケージを使用しません。バンドルを使用します。つまり、バンドルの1つのパッケージを使用する場合、Eclipseはバンドルをコンパイルしますが、そのバンドルからインポートされない残りのパッケージの使用に関する問題は報告されません。
あなたは(あなたは人間です)すべてが大丈夫だと考え、デプロイメントのためにバンドルをアップロードしますが...バンドルは実行時に壊れます。
この問題が今日(私にとって!)起こったので、私はそれについて確信しています。
良い解決策はEclipseクラスパスコンテナーを変更することですが、これを行わない場合は、パッケージの代わりにバンドルを必要とするこの種の問題を回避し、上記の価格を支払うこともできます(下位互換性なし)バンドル間のコード移動)。