SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Java EE 6 開発入門

JSR-299を利用した依存性注入

JavaEE6 開発入門(6)


  • X ポスト
  • このエントリーをはてなブックマークに追加

複数の実装クラスと識別子@Qualifierの利用

 冒頭で紹介したアプリケーションの例にあった新品と中古品の販売機能など、1つのインターフェースを実装するクラスを複数作成するアプリケーションが考えられます。サイコロの実装で例えると、SimpleDiceは1から6の目を返しますが、例えば他にも違った目を出すパターンのサイコロが必要になる場合や、目の出方を偏らせるアルゴリズムを実装したサイコロの目が欲しい場合などが考えられます。具体的には次のようなクラスを用意します。

[リスト5]異なるサイコロの目を返す ExtendDice.java
package sample.beans;

import java.util.Random;

public class ExtendDice implements IDice {

    public int nextValue() {
        Random rnd = new Random(System.currentTimeMillis());
        
        int retValue = rnd.nextInt(6) +15; …①
        
        return retValue;
    }

    public String getMessage() {
        return "ExtendDice"; …②
    }
}

 ①では15から20の目を返すようにした機能にし、②ではExtendDiceの結果であることを示す文字列を返します。

 機能の実装は以上で完了しましたので、これを実際にコンテナで動かそうとすると、コンソールで次のエラーログが出力され動きません。

図6 ExtendDice.javaを含めて実行したときのコンソール
図6 ExtendDice.javaを含めて実行したときのコンソール

 コンソールを見ると、

Ambiguous dependencies for type [IDice] with qualifiers [@Default] at…

とあります。これは@Injectで指定したインターフェースに対する実装クラスを取得しようとした際に対象が複数あるためコンテナが特定できない(注4)からです。

 そのため、SampleManagedBeanのIDiceに対して実行時にはどのクラスを使用するのかを指定する必要があります。これを定義するものがCDIの限定子と呼ばれるもので、限定子は@Qualifierで定義されるアノテーションです。

図7 限定子を使ってインスタンスを取得するクラスを定義
図7 限定子を使ってインスタンスを取得するクラスを定義

注4

 Ambiguous dependencies for type [IDice] = IDice型に対して依存性の定義があいまいであることを通知する

 識別子はNetBeansのクラス作成ウィザードから簡単に作成できます。NetBeansの左上にある[プロジェクト]ペインのソースパッケージ上で[新規作成]を選びます。すると次の作成ウィザードが表示されますので、カテゴリから[Contexts and Dependency Injection]を選び、[限定子の種類]を選択し、[次へ]を押します。

図8 限定子の作成ウィザード
図8 限定子の作成ウィザード

 続いて作成する限定子の名称などを入力します。今回はDiceと入力して[完了]を押します。すると次の限定子Diceが生成されます。

[リスト6]ウィザードから生成されたDice限定子 Dice.java
package sample.beans;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;

@Qualifier …①
@Retention(RUNTIME) …②
@Target({METHOD, FIELD, PARAMETER, TYPE}) …③
public @interface Dice {
}

 ① @Qualifierで、このクラスの定義は限定子であることを宣言しています。

 ② @Retentioでは対象のオブジェクトの寿命を設定することができます。RUNTIMEを指定することでランタイムが存在している間は有効であることを設定します。

 ③ @Targetはこの限定子が適用される対象を定義します。定義はクラスなどの型、メソッド、パラメータ、フィールドから選択することができます。

 この限定子を定義することで、@Injectを使ってインスタンス取得する際に、どのクラスを利用するのかを指定できます。指定方法は限定子のクラス名と同じ名前を指定しますので@Diceで記述します。

 では具体的に限定子を使ってサイコロの目を取得するインスタンスを定義しましょう。今回はExtendDiceを利用します。まずはサイコロのインスタンスを利用するSampleManagedBeanです。

[リスト7]Dice限定子でインスタンスを指定したManagedBean SampleManagedBean.java
package sample.beans;

import javax.inject.Named;
import javax.inject.Inject;

@Named(value = "sample")
public class SampleManagedBean {

    public SampleManagedBean() {
    }
    
    @Inject
    @Dice …①
    private IDice dice;
    
    public int nextValue() {
        return dice.nextValue();
    }
    
    public String getMessage() {
        return dice.getMessage();
    }
}

 変更箇所は①のDice限定子だけです。続いて限定子で取得されるクラス側のExtendDiceです。

[リスト8]Dice限定子で指定されたクラス ExtendDice.java
package sample.beans;

import java.util.Random;

@Dice …①
public class ExtendDice implements IDice {

    public int nextValue() {
        Random rnd = new Random(System.currentTimeMillis());
        
        int retValue = rnd.nextInt(6) +15;
        
        return retValue;
    }

    public String getMessage() {
        return "ExtendDice";
    } 
}

 変更箇所は①の@Dice限定子の追加だけです。これにより@InjectでIDice型のインスタンス取得が@Diceによって特定されました。正しく定義されていれば、コンテナの再起動後には次の図のように、サイコロから取得した値は15以上の値となり、ExtendDiceから値を取得したことを示すメッセージも表示されます。

図9 限定子でExtendDiceを指定した後の画面
図9 限定子でExtendDiceを指定した後の画面

まとめ

 以上のように、CDIを使ったインスタンス取得と限定子の定義を使うことで、とても簡単に実装クラスの置き換えが設定できることも分かりました。

 次回は送信フォームを利用したアプリケーションの例を紹介します。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Java EE 6 開発入門連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 東 浩二(アズマ コウジ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/6569 2012/06/10 12:15

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング