Seasar2 [No.3] S2Container

#1. S2Containerとは

- DIコンテナ
- コンポーネントの管理を行う機能を提供する。
※コンポーネント = Javaオブジェクトのこと。
- S2Containerはコンポーネントの生成、コンポーネントの初期化、コンポーネントの取得を提供する。
- Dependency Injectionをおこなう軽量コンテナの実装 
⇒Dependency Injectionをおこなう軽量コンテナのSeasar2における実装のこと。

#2. S2Containerの使用方法
Seasar2とDIの概念に慣れるためのサンプル。
###(1)「**Hello,World!**」と表示させる

```java:IMessageTarget
public interface IMessageTarget {
     public String getName();
}
```

```java:IMessageProvider
public interface IMessageProvider {
     public void setMessageTarget(IMessageTarget messageTarget);
     public String getMessage();
}
```

```java:DefaultMessageTarget
public class DefaultMessageTarget implements IMessageTarget{
     @Override
     public String getName(){
          return "World";
     }
}
```

```java:HelloMessageProvider
public class HelloMessageProvider implements IMessageProvider{
     private IMessageTarget messageTarget;
     @Override
     public void setMessageTarget(IMessageTarget messageTarget){
          this.messageTarget = messageTarget;
     }
     @Override
     public String getMessage(){
          return "Hello, " +messageTarget.getName() + "!";
     }
}
```
app.diconに↓の2行をcomponentsタグ内に追記する

```xml:app.dicon
<component name="messageTarget" class="co.jp.finance.money.action.DefaultMessageTarget" instance="singleton" />
<component name="messageProvider" class="co.jp.finance.money.action.HelloMessageProvider" instance="singleton" />
```
起動クラス↓

```java:Main.java
public class Main {
     public static void main(String[] args) {
          //S2Containerを初期化(app.diconを読み込み)
          SingletonS2ContainerFactory.init();
          //IMessageProviderインタフェースを実装したコンポーネントを取得
          IMessageProvider messageProvider = SingletonS2Container.getComponent(IMessageProvider.class);
          //メッセージを表示
          System.out.println(messageProvider.getMessage());
          //S2Containerを破棄
          SingletonS2ContainerFactory.destroy();
     }
}
```
実行すると下記のように表示される

```text
Hello,World!
```

###(2)「**Hello,Seasar2!**」と表示させる(コンポーネントの差し替え)
IMessageTargetの実装クラスを差し替える(新しい実装クラスの作成)

```java:SeasarMessageTarget
public class SeasarMessageTarget implements IMessageTarget {
     @Override
     public String getName() {
          return "Seasar2";
     }
}
```
app.diconを以下に編集する

```xml:app.dicon
<component name="messageTarget" class="co.jp.finance.money.action.SeasarMessageTarget" instance="singleton" />
```

実行すると、DefaultMessageTargetの代わりにSeasarMessageTargetがDIされて

```text
Hello,Seasar2!
```
と表示される。

実装コードに手を加えず新しい実装コードを作成してコンポーネントを差し替えることができるのがDIの大きなメリットの1つ。
app.diconファイルを修正することでコンポーネントを差し替えましたが、diconファイルを自動的に切り替える機能もあるため、ソースコードやdiconファイルを一切修正せずにコンポーネントを差し替えることもできる。

---

#3. S2Containerの初期化
1つのVM上で1つのコンテナが存在すれば良いケースでは、**SingletonS2Container**を利用します。
Singleton"2Containerを初期化するには**SingletonS2ContainerFactory.init()**を呼び出す。
Singleton"2Containerはデフォルトではクラスパスルートのapp.diconでコンテナを初期化します。

処理の終了後にはコンテナを廃棄するために**SingletonS2ContainerFactory.destroy()**を呼び出す。

```java
//初期化時に読み込むdiconファイルを変更する場合
SingletonS2ContainerFactory.setConfigPath()
//コンテナを初期化
SingletonS2ContainerFactory.init()

//コンテナを廃棄
SingletonS2ContainerFactory.init()
```

#4. コンポーネントの取得
S2Containerからコンポーネントを取得するには
**S2Container.getComponent()**を使用する。

```
ImessageProvider messageProvider = SingletonS2Container.getComponent(IMessageProvider.class);
```