[基本機能] DIコンテナ

DIコンテナとは、Dependency Injection Containerの略で、依存性注入を行えるコンテナの事です。
依存性注入とは、例えば、ある機能Aを提供するABeanがある時、Aの機能を提供するためには、その下位機能として機能Bが必要であるとします。 機能BがBBeanによって提供されるならば、ABeanが機能Aを提供するためには、BBeanが存在する事が前提になります。 このような場合、ABeanはBBeanに依存していると言います。
DIコンテナは、この依存関係を満たすために、まずBBeanを生成して、次にABeanを生成します。更に、ABeanにBBeanの参照を渡してあげます。これが、依存性注入です。

関連するパッケージは、以下です。

概要

Nimbusは、サービスと呼ばれるライフサイクルを持ったオブジェクトをメモリ中にホスティングして、サービスを提供するDIコンテナを持ちます。
サービスをホスティングするには、サービス定義と呼ばれるXML定義ファイルで、サービスを配置します。サービス定義では、サービスの起動順序を制御するためにサービス同士の依存関係を定義したり、サービスに設定値を定義したりする事ができます。

サービス

Nimbusにおけるサービスとは、ライフサイクルを持ち、アプリケーションに対して機能を提供するJava Beansです。

ライフサイクルは、生成create)、開始(start)、停止stop)、破棄destory)の4つのサイクルです。
生成は、サービス内部のインスタンス変数の初期化などを行います。また、生成の直後に依存性注入が行われます。
開始は、サービスが機能を提供する準備を行います。開始が完了すると機能提供が可能になります。
停止は、サービスが提供する機能を停止します。
破棄は、サービス内部のインスタンス変数を破棄します。

通常、サービスは、以下の3つのインタフェースを実装します。

  • アプリケーションに対して、機能を提供する任意のインタフェース
  • DIコンテナに対して、ライフサイクルを提供するServiceインタフェース
  • JMXサーバに対して、管理機能を提供するMBeanインタフェース

但し、これら3つのインタフェースを実装しないPOJO(Plained Old Java Object)でも、サービスとしてホスティングする事もできます。
Nimbusでは、これらの3つのインタフェースを実装した様々なサービスを提供します。また、アプリケーション開発者が独自のサービスを実装して、ホスティングさせる事もできます。

以下に基本的なサービスの実装例を示します。

アプリケーション向け機能を提供するインタフェースMessage.java

  1. public interface Message{
  2. public void displayMessage();
  3. }

JMXサーバに対して、管理機能を提供するMBeanインタフェースMessageServiceMBean.java

  1. public inetrface MessageServiceMBean extends jp.ossc.nimbus.core.ServiceMBean{
  2. public void setMessage(String message);
  3. public String getMessage();
  4. }

サービスMessageService.java

  1. public class MessageService extends jp.ossc.nimbus.core.ServiceBase implements Message, MessageServiceMBean{
  2. private String message;
  3. // JMXサーバ向けのMBeanインタフェースを実装
  4. public void setMessage(String message){
  5. this.message = message;
  6. }
  7. public String getMessage(){
  8. return message;
  9. }
  10. // DIコンテナ向けのServiceインタフェースを実装
  11. // jp.ossc.nimbus.core.ServiceBaseを継承する事で、実装したいライフサイクルだけを実装する事ができる
  12. public void startService() throws Exception{
  13. if(message == null){
  14. throw new Exception("メッセージが設定されていません");
  15. }
  16. }
  17. // アプリケーション向けのインタフェースを実装
  18. public void displayMessage(){
  19. System.out.println(message);
  20. }
  21. }

サービス定義

Nimbusでは、XMLファイルでサービスをDIコンテナに配置する定義を記述します。この定義ファイルをサービス定義ファイルと呼びます。

サービス定義ファイルでは、おおまかには以下を定義する事ができます。

  • デフォルトのログサービスを定義する
  • サーバ環境変数を定義する。
  • サービスをグルーピングするサービスマネージャを定義する
  • マネージャ環境変数を定義する。
  • サービスを定義する
    • サービスの名前を定義する
    • サービスのクラス名を定義する
    • サービスの生成種別(シングルトン、ファクトリ、スレッドローカル、テンプレート)を定義する
    • サービスのコンストラクタインジェクションを定義する
    • サービスのフィールドインジェクションを定義する
    • サービスの属性インジェクションを定義する
    • サービスのメソッドインジェクションを定義する
  • サービスの依存関係を定義する

サービス定義ファイルの詳細な、定義ルールは、DTDファイルを参照して下さい。

以下に、簡単なサービス定義の例を示します。

service-definition.xml

  1. <?xml version="1.0" encoding="Shift_JIS"?>
  2. <!DOCTYPE server PUBLIC
  3. "-//Nimbus//DTD Nimbus 1.0//JA"
  4. "http://nimbus.sourceforge.jp/dtd/nimbus-service_1_0.dtd">
  5. <server>
  6. <manager>
  7. <service name="Message"
  8. code="MessageService ">
  9. <attribute name="Message">こんにちは</attribute>
  10. </service>
  11. </manager>
  12. </server>

以下にサービス定義の読み込み方法、及びサービスの取得方法を示します。

  1. import jp.ossc.nimbus.core.ServiceManagerFactory;
  2. // サービス定義を読み込む
  3. if(ServiceManagerFactory.loadManager("service-definition.xml") && ServiceManagerFactory.checkLoadManagerCompleted()){
  4. System.out.println("サービス定義の読み込みに成功しました。");
  5. }else{
  6. System.out.println("サービス定義の読み込みに失敗しました。");
  7. System.exit(-1);
  8. }
  9. // サービスを取得する
  10. Message message = (Message)ServiceManagerFactory.getServiceObject("Message");

サンプルは、以下。