OSGiの概念を理解します。 パズルのアプローチに従うようにしてください
公開: 2013-04-20OSGi
は、そのモジュール性アプローチとモジュール間の論理境界を強制する機能のおかげで、今日非常に人気がありました。 私たちが最初にそれを発見したとき、問題はそれがどのように機能するかをどこから理解し始めるかです。
OSGiの概念を理解するために、パズルのアプローチに従うようにします。アイデアは、このテクノロジーの些細な部分から始めて、見つかったものに関連する他の部分を検索することです。 そして、パズルを組み立てるために、OSGiの内部設計を検出するのに役立つJArchitectの支援を受けます。
より具体的には、OSGiテクノロジーを使用するアプリケーションをJArchitectで分析します。これは、OSGiコンテナーequinoxを使用する有名なEclipseIDEに関するものです。
典型的なOSGiの定義から始めましょう:
OSGiは、今日の大規模な分散システムと小規模な組み込みアプリケーションにモジュラーアーキテクチャを提供することにより、複雑さを軽減します。 社内および既製のモジュールからシステムを構築すると、複雑さが大幅に軽減され、開発と保守の費用が大幅に削減されます。 OSGiプログラミングモデルは、コンポーネントベースのシステムの可能性を実現します。
OSGiの些細な部分はモジュール性です。OSGiモジュールとは何かを発見しましょう。
OSGIモジュールはバンドルと呼ばれるため、すべてのアプリケーションは少なくとも1つのバンドルで構成されます。
これらのバンドルはコンテナ内で実行され、コンテナがモジュールを管理する各モジュラーアプローチとして、どのコントラクトがコンテナに統合されるすべてのモジュールを実装する必要があるかが問題になります。
バンドルorg.eclipse.equinox.jsp.jasperを例として取り上げ、実装されているすべてのインターフェイスを検索して、次のCQLinqリクエストを実行できるようにします。
1 2 3 4 |
from t in Types where t . ParentProject . Name ==” org . eclipse . equinox . jsp . jasper_1 . 0.300.v20110502 “ let interfaces = t . InterfacesImplemented from i in interfaces select i |
OSGiパッケージのBundleActivatorインターフェースが実装されています。このインターフェースには、バンドルの開始と停止をカスタマイズするのに役立つstartとstopの2つのメソッドが含まれています。
バンドルのもう1つの特異性は、そのマニフェストファイルです。これは、org.eclipse.equinox.jsp.jasperマニフェストファイルの一部です。
1 2 3 4 5 6 7 8 9 |
Manifest - Version : 1.0 Bundle - Localization : plugin Bundle - RequiredExecutionEnvironment : CDC - 1.0 / Foundation - 1.0 , J2SE - 1.3 Bundle - SymbolicName : org . eclipse . equinox . jsp . jasper Eclipse - LazyStart : true Eclipse - SourceReferences : scm : cvs : pserver : dev . eclipse . org : / cvsroot / rt : org . eclipse . equinox / server - side / bundles / org . eclipse . equinox . jsp . jaspe r ; tag = v20110502 Bundle - Activator : org . eclipse . equinox . internal . jsp . jasper . Activator |
このマニフェストには、BundleActivatorインターフェイスを実装するバンドルアクティベータークラスの指定など、コンテナーに必要ないくつかのメタ情報が含まれていることがわかります。
バンドルはパズルの最初のピースを表しており、バンドルの簡略化された表現は次のとおりです。
そして、Eclipseで使用されるすべてのバンドルを把握するために、BundleActivatorインターフェースを実装するすべてのクラスを検索してみましょう。
1 2 |
from t in Types where t . Implement ( “ org . osgi . framework . BundleActivator “ ) select new { t , t . NbBCInstructions } |
誰がバンドルを管理し、BundleActivatorメソッドを呼び出しますか?
それを発見するには、直接または間接的にBundleActivator.startを呼び出すメソッドを検索してみましょう。
1 2 3 4 |
from m in Methods let depth0 = m . DepthOfIsUsing ( “ org . eclipse . osgi . framework . internal . core . BundleContextImpl . startActivator ( BundleActivator ) “ ) where depth0 > = 0 orderby depth0 select new { m , depth0 } |
バンドルは、起動時にOSGiフレームワークによってアクティブ化されます。 フレームワーククラスは、equinoxコンテナによって開始されます。 また、コンテナの起動時に何が起こるかをよりよく理解するために、コンテナの起動時に実行されるアクションを次に示します。
コンテナーが起動されると、OSGiフレームワークが初期化され、フレームワークはインストールされているすべてのバンドルを取得し、それぞれについてBundleHostクラスのインスタンスを作成し、見つかったバンドルをリポジトリーに保管します。
BundleHostクラスは、start、stop、uninstall、updateなどのメソッドを含むBundleインターフェイスを実装します。これらのメソッドは、バンドルのライフサイクルを管理するために必要です。
したがって、2番目のパズルのピースはOSGiコンテナーであり、フレームワークを初期化するEquinoxlauncherによって起動されます。 フレームワーククラスは、バンドルのロードとアクティブ化を担当します。
バンドルとコンテナに関するいくつかの基本的な概念を発見した後、バンドルの内部を深く掘り下げて、それらが内部でどのように機能するかを発見しましょう。
例として、org.eclipse.equinox.http.servletバンドルを取り上げ、そのActivatorクラスのstartメソッドによって呼び出されるメソッドを検索してみましょう。

このバンドルはサービスを作成し、それをコンテナーに登録します。 OSGiのサービスは、標準のJavaクラスまたはインターフェースによって定義されます。 通常、Javaインターフェースはサービスインターフェースを定義するために使用されます。 このサービスは、バンドルが相互に通信するために使用する必要のある推奨される方法です。
サービスを使用するためのいくつかの便利なシナリオを次に示します。
- バンドルから他のバンドルに機能をエクスポートします。
- 他のバンドルから機能をインポートします。
- 他のバンドルからのイベントのリスナーを登録します。
前の依存関係グラフからのもう1つの注意点は、サービスファクトリを使用してサービスインスタンスを作成することです。
パズルの3番目のピースは、OSGiサービスレイヤーです。各バンドルは、コンポーネント設計アプローチを実施するいくつかのサービスを使用または宣言できます。これが、OSGiバンドルの新しい表現です。
バンドルがサービスを使用して他のバンドルと通信する場合、他のjarとどのように通信しますか?
バンドルを開発して別のjarのクラスを使用しようとすると、期待どおりに機能しないことに驚かれる可能性があります。その理由は、ClassLoaderがOSGiコンテナーにフックされているため、どのメソッドがjavaを呼び出すかを検索するためです。 lang.Thread.setContextClassLoader。
1 2 |
from m in Methods where m . IsUsing ( “ java . lang . Thread . setContextClassLoader ( ClassLoader ) “ ) select new { m , m . NbBCInstructions } |
EquinoxLauncherを含む多くのメソッドがそれを呼び出します。 そのため、バンドルがクラスインスタンスを作成しようとするたびに、OSGiコンテナーは、コードがこのアクションの実行を許可されているかどうかを確認します。ここで、マニフェストファイルにインポートおよびエクスポートされたパッケージの役割があります。
1 2 3 4 |
Export - Package : org . eclipse . equinox . http . servlet ; version =” 1.1.0 ″ Import - Package : javax . servlet ; version =” 2.3 ″ , javax . servlet . http ; version =” 2.3 ″ , org . osgi . framework ; version =” 1.3.0 ″ , org . osgi . service . http ; versi on =” [ 1.2 , 1.3 ) ” |
バンドルは、明示的にエクスポートおよびインポートされたパッケージを宣言します。それを確認するために、org.eclipse.equinox.http.servletバンドルで使用されるパッケージを検索し、インポートされたパッケージのみを使用するかどうかを確認します。
1 2 |
from n in Packages where n . IsUsedBy ( “ org . eclipse . equinox . http . servlet_1 . 1.200.v20110502 “ ) select new { n , n . NbBCInstructions } |
使用されているすべてのパッケージがマニフェストファイルのインポートパッケージセクションで指定されていることがわかります。
ただし、エクスポートされたパッケージは、他のバンドルから使用できるパッケージを表しています。 これはExportedPackageインターフェースで表され、このインターフェースを使用してコンテナークラスを検索できます。
1 2 |
from t in Types where t . IsUsing ( “ org . osgi . service . packageadmin . ExportedPackage “ ) select new { t , t . NbBCInstructions } |
この新機能の興味深い点は、バンドルに明確に定義された境界があり、バンドルが使用するものとサービスとして公開するものが非常に明確に指定されていることです。
他のツールを使用して、インポートされたパッケージを使用するチェックを強制できます。たとえば、CQLinqを使用すると、プロジェクトが指定されたパッケージ以外のパッケージを使用するたびに警告するルールを記述できますが、実行環境でこのチェックを行うことをお勧めします。これらのルールを破ることはできません。
インポートおよびエクスポートされたパッケージを処理するこの機能は、OSGiモジュール層によって管理されており、パズルの4番目のピースでした。
OSGiコンテナーに戻って、それが提供するサービスを見つけましょう。
コンテナサービス
コンテナがEquinoxLauncherクラスによって起動され、フレームワーククラスがバンドルを初期化して起動する前に発見したように、提供されているサービスを検出するために、フレームワーク初期化メソッドで使用されるすべてのクラスを検索しましょう。
1 2 |
from t in Types where t . IsUsedBy ( “ org . eclipse . osgi . framework . internal . core . Framework . initialize ( FrameworkAdaptor ) “ ) select new { t , t . NbBCInstructions } |
BundleRepository、BundleHost、PackageAdminImpl、ServiceRegistryなど、一部のクラスは以前にすでに検出されています。
他のクラスはどうですか?
- StartLevelManager:
各OSGiバンドルは、サーバーがバンドルの相対的な開始順序と停止順序を制御できるようにする開始レベルに関連付けられています。 サーバーフレームワークのアクティブな開始レベル以下の開始レベルを持つバンドルのみがアクティブである必要があります。 通常、開始レベルが小さいバンドルは、より早く開始される傾向があります。 - SecurityAdmin:
セキュリティ層は、バンドル機能を事前定義された機能に制限することにより、セキュリティの側面を処理します。 - イベントマネージャ:
イベント管理サービスは、イベントを処理するためのパブリッシュ/サブスクライブモデルを提供します。 これは、OSGiイベント管理サービス仕様に従って実現されます。イベント管理サービスは、イベントチャネルを挿入することにより、イベントパブリッシャーとイベントサブスクライバー(イベントハンドラー)の間でイベントをディスパッチします。 パブリッシャーはチャネルにイベントを投稿し、イベントチャネルはどのハンドラーに通知する必要があるかを定義します。 したがって、パブリッシャーとハンドラーはお互いを直接知ることができず、イベント管理が簡素化されます。
OSGiの全体像
前に説明したすべてのパズルのピースを組み立てましょう。次のOSGiの画像が表示されます。
このアーキテクチャには、次の興味深い利点があります。
- 単純。
- 複雑さの軽減。
- 簡単な展開。
- 安全。
何がそれを非常に魅力的で迂回する価値があるのか、そしてそれを深く研究すればあなたはあなたの時間を無駄にすることはありません。