ひこぽんのーと

覚書と雑記です。

JavaEE 7をやってみよう。 CDI その5

その4のつづき。

もはや、限定子を使いまわす、ということからは外れてしまうのだが、
気を取り直して続きを書く。

package warship;

〜〜 import 省略 〜〜

@Named(value="fleet")
@RequestScoped
public class Fleet {
    @Inject
    @First
    private IWarShip firstShip;

〜〜 以下、省略 〜〜
}

ここのメンバに任意でインジェクション対象を指定できれば良いな、と考えて、
CDIについてさらに調べてみた。
すると、メソッドの戻り値をメンバにインジェクションする方法があるとのこと。
対象メソッドにProcedureアノテーションを付加すれば良いらしい。
しかもクラスはManaged Beanから分けることができる。

というわけで、インジェクション対象を決定するクラスを作ってみた。

インジェクション対象を決定するクラス
フラグによって、インジェクション対象のクラスを切り替えられるようにしてみた。
ちなみに、このクラスのメソッドに限定子を持たせるため、
各艦艇クラスに付加した限定子は削除する必要がある。
また、サンプルの艦隊名もManaged Beanに固定だったものを、
このクラスのgetFleetNameメソッドの戻り値に依るように直した。
package warship;

import javax.enterprise.context.Dependent;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;

import warship.impl.Akatsuki;
import warship.impl.Aoba;
import warship.impl.Furutaka;
import warship.impl.Hibiki;
import warship.impl.Ikazuchi;
import warship.impl.Inazuma;
import warship.impl.Kako;
import warship.impl.Kinugasa;
import warship.qualifier.First;
import warship.qualifier.Forth;
import warship.qualifier.Second;
import warship.qualifier.Third;

@Dependent
public class WarShipProcedure {
    boolean destroyers = true;
    
    @Produces
    @RequestScoped
    @First
    public IWarShip createFirstShip() {
        IWarShip result = new Furutaka();
        if (destroyers) {
            result = new Akatsuki();
        }
        return result;
    }

    @Produces
    @RequestScoped
    @Second
    public IWarShip createSecondShip() {
        IWarShip result = new Kako();;
        if (destroyers) {
            result = new Hibiki();
        }
        return result;
    }

    @Produces
    @RequestScoped
    @Third
    public IWarShip createThirdShip() {
        IWarShip result = new Aoba();;
        if (destroyers) {
            result = new Ikazuchi();
        }
        return result;
    }

    @Produces
    @RequestScoped
    @Forth
    public IWarShip createForthdShip() {
        IWarShip result = new Kinugasa();
        if (destroyers) {
            result = new Inazuma();
        }
        return result;
    }
    
    @Produces
    public String getFleetName() {
        String result = "第六戦隊";
        if (destroyers) {
            result = "第六駆逐艦隊";
        }
        return result;
    }
}

実行するとこんな感じ。

destroyers = trueの場合
f:id:nagamitsu1976:20150803142542p:plain
destroyers = falseの場合
f:id:nagamitsu1976:20150803151705p:plain

この方法は単体テストとか、条件によって差し込むモジュールを変えたい時に有効かな。
あとは旧モジュールから新モジュールへ変えたいときなど、
元のクラスを変更せずに、
プロシージャクラスの変更で切り替えが済むので便利ですな。
もっとも、この辺、Springだと設定ファイルで、Giuceだと同様の設定クラスがあるので、
それとなんら変わらんわなぁ。