Contexual Injection

JBossマイクロコンテナは状態機械(state machine)です。マイクロコンテナは、デプロイされたPOJOを管理するだけではなくて、起動・停止などのデプロイの状態も一緒に管理し、POJO間の依存関係を解決します。

普通のDIコンテナでは名前やタイプを使って依存性の注入をしますが、マイクロコンテナはサービスの実行環境として使われるのを想定しているので、サービスの起動中や再デプロイが発生した場合など、状態を無視して注入してしまうとすぐに実行時エラーになってしまいます。だから、依存先のサービスが準備できていないときはそちらの作業が終了してから注入をするとか、状態を意識した制御が必要になります。

この状態を意識した依存性の管理は、マイクロコンテナで始めて導入されたコンセプトではありません。世間でDIコンテナが登場する前から、JBossJMXマイクロカーネルは、まさにこの仕事をMBean間の依存関係解決という形で実現してきました。JBoss5のマイクロコンテナはこの仕事をJMX MBeanからPOJOへ、MBeanインタセプタからAOPという形へ、サービス実行環境をより汎用的かつポータブル*1フレームワークに進化させているのです。

マイクロコンテナで依存性の管理をしているのはControllerで、そこで管理されるサービスの状態はControllerContextです。このControllerContextはPOJOの状態を保持しています。この状態としては、たとえば、デプロイの状態、他のPOJOとの依存関係、モード(自動起動/手動起動)などがあります。

次の例は、マイクロコンテナからPOJOを取り出す具体例です。この例ではPOJOを取り出すのに、まずControllerContextを取り出し、そのControllerContextからターゲットとなるPOJOを取り出しています。

private final static String HRSERVICE = "HRService";
...
// Start JBoss Microcontainer
bootstrap = new EmbeddedBootstrap();
bootstrap.run();
kernel = bootstrap.getKernel();
controller = kernel.getController();
...
ControllerContext context =
controller.getInstalledContext(HRSERVICE);
if (context != null) { manager = (HRManager) context.getTarget(); }

昨日の日記でDeployment callbackを紹介しましたが、これは後からデプロイによってPOJOが動的に追加された場合に、POJOの間の参照関係を実行時に解決することができます。このように、マイクロコンテナのDIは、デプロイされる実行環境の状況が動的に変わることを想定して作られています。まさにプラガブルでダイナミックな依存性注入の仕組みです。

参考:JBoss Microcontainer: Embeddable JBoss

*1:「ポータブル」というのは、マイクロコンテナがあれば、JBoss Application Server以外の環境でもJBossのサービスを動かし、サービスを連携させることができるというビジョンからきています