Locked History Actions

guice/Manual/Integration/OSGi

OSGi

OSGiはEclipseやGlassFishなどの多くのプロジェクトで用いられている動的モジュールシステムである。 OSGi中のモジュールはバンドルとして知られ、それは基本的には付加的なメタデータを持つJARファイルである。 このメタデータはバンドルの識別子、必要とするパッケージ、それが提供するものを記述する。 GuiceはOSGiメタデータを第二リリースにて追加した。 いまや現代のOSGiコンテナにバンドルとしてインストールできるということである。

OSGiコンテナは、共有サービスレジストリも提供する。 それは一つJVMの中で、バンドルがそのサービスをその場で公開したり利用したりし、それらの動的なコラボレーションを実現する。 Guiceは、サードパーティ製のpeaberry拡張を経由して、OSGiサービスレジストリに統合することができる。

peaberry無しでGuiceをOSGi環境で使うことができますか?

短い答え:Yes!

長い答え: GuiceはOSGiコンテナの中でトランスペアレントにAOPをサポートするコードを含む正当なOSGiバンドルである。 あなたの複数のOSGiバンドルとの間でモジュールバインディングやインジェクタを共有することができるし、 peaberry拡張無しでpublicメソッドに対するメソッドインターせぷしょンを使うことができる。

peaberryのメリットは?

peaberryは動的サービスを公開したり利用するためのスムーズなAPIを提供している。 そのままの状態でOSGiサービスレジストリとの統合を提供するし、他のレジストリベースのフレームワークのためのプラグインサポートも持っている。 これはSpringの動的モジュールと等価であると考えられるが、しかしさらにタイプセーフでありGuiceのパフォーマンスを持つ。 また、OSGiに限らず他のサービスフレームワークと協調することができる。

peaberryを使えばOSGiサービスを他のGuiceバインディングと同じ用に注入することができる。 サービスが更新されても、バインディングは有効でトランスペアレントに動作しつづける。 また、OSGiサービスとして、インスタンス(あるいはバウンドタイプ)を公開・非公開するためのエクスポートハンドルを注入することができる。 さらに、注入されたサービスの変更を監視するoutjectionの形式を使うことができる。

Last, but definitely not least, peaberry brings OSGi service support to your existing Guice application without introducing any OSGi specific types. You can switch between a fixed Java instance or an OSGi service for the same injection point just by changing your binding modules. What are the constraints of using Guice's OSGi support?

Guice uses bytecode generation for AOP, faster reflection, and to proxy circular dependencies. The generated bytecode must be able to see both the original client type (available from the client classloader) and AOP internals (available from the Guice classloader), but in OSGi these classloaders will be isolated from one another. The client classloader will only see its own types and imports, while Guice will only see its own types and imports.

To support AOP in OSGi without requiring clients to know about AOP internals, or vice-versa, Guice automatically creates and manages bridge classloaders that bridge between client and Guice classloaders. The bridge classloaders also support eager unloading of proxy classes, which reduces the potential for memory leaks when reloading bundles.

This is only possible when the types involved are not package-private (because by definition package-private types are not visible from other classloaders). If you attempt to use AOP on package-private types while running inside an OSGi container you will see the following exception:

 ClassNotFoundException: com.google.inject.internal.cglib.core.ReflectUtils

because bridging wasn't possible. If you need to use AOP with package-private types or methods in OSGi then you can always put Guice and the AOP Alliance JAR on the main classpath and use the org.osgi.framework.bootdelegation property to expose the Guice packages, like so:

 "-Dorg.osgi.framework.bootdelegation=org.aopalliance.*,com.google.inject.*"

You can still dynamically unload and reload bundles when using bootdelegation with Guice, but you would need to restart the JVM to replace the Guice bundle itself. This is much less likely to happen compared to upgrading client bundles, and it's usually fine to do a full shutdown when a key production service is upgraded. This also avoids potential problems like serialization-compatibility for HTTP session objects.