Java EE 6のDIであるCDIとは
Java EE 6では、DIからさらに利便性と機能を追加したCDI(注3)が採用されています。本稿で利用しているGlassfishでは最初からCDIを利用できる状態になっています。
従来のDIはJavaのコードからクラス生成の依存性を取り除きますが、DIで管理するクラスが増えると、クラス生成の設定ファイルが膨大になってしまう欠点がありました。また、DIで管理するクラスは常にインターフェースを作成しなければなりません。一般的な業務アプリケーションを作成した場合、業務処理の一つのインターフェースに対し1つのクラスになることが多く、その結果、管理しなければならないコード量が増えてしまいました。
Java EE 6のCDIではこれらの不便な点を解消してくれます。具体的には、CDIで管理されたクラスの生成に関する設定が大幅に減少し、どのインスタンスを生成するかは簡単なアノテーションで記述しておくだけで、後はCDIコンテナが自動的に管理します。また、インスタンス生成をするクラスを特定する方法も、NetBeansがもつ生成ウィザードから簡単に行えますので、とても手軽に作成できます。
本稿ではWebアプリケーションのサンプルを通して、CDIによる依存性注入の方法と作成の方法を紹介します。
Context and Dependency Injectionの略。クラスの依存性注入とスコープ管理を提供する仕様。
依存性注入する対象を宣言する @Inject
CDIで依存性を注入するには@Injectアノテーションをメンバ定義の先頭に追加するだけです。@Injectは、任意のフィールドやメソッドに指定が可能で、取得できる内容は@Injectで宣言したインスタンスです。次に実際のコード例を示します。
// ManagedBean宣言 package sample.beans; import javax.inject.Named; import javax.inject.Inject; @Named(value = "sample") …① public class SampleManagedBean { public SampleManagedBean() { } @Inject …② private IDice dice; public int nextValue() { return dice.nextValue(); …③ } public String getMessage() { return dice.getMessage(); …④ } }
依存性注入に関する記述は太字で示した@Injectの1行のみになります。
①の宣言によって、SampleManagedBeanクラスがManagedBeanとしてCDIの管理下に入ります。value属性でこのアプリケーションから参照するときの名称を定義します。
②でIDiceを実装したインスタンスが、CDIコンテナ経由でセットされます。
このIDiceはインターフェースで、その機能はサイコロを振ってその目を返す簡単な機能を定義するものです。サイコロの値を返す処理は③の箇所で利用しています。
④も③同様、サイコロを振るクラスからメッセージを取得します。
DIコンテナでは利用するクラスのインターフェースを指定することで、DIコンテナの設定ファイルやアノテーションから取得するインスタンスを特定します。CDIの場合は特に設定ファイルは必要なく、@Injectで指定するだけで生成するインスタンスを自動的に特定します。
次に、CDI管理されるサイコロの機能を提供するインターフェースとクラスの定義です。まずはサイコロの目を返すインターフェースを作成します。
package sample.beans; public interface IDice { public int nextValue(); …① public String getMessage(); …② }
①で次のサイコロの目を返す機能、②はメッセージを返す機能をそれぞれ提供します。
続いてCDI管理されるサイコロの機能を作成します。IDiceインターフェースを実装した単純なサイコロの目を返す機能を実装したのが次のSimpleDiceです。
package sample.beans; import java.util.Random; public class SimpleDice implements IDice { public int nextValue() { …① Random rnd = new Random(System.currentTimeMillis()); int retValue = rnd.nextInt(6) +1; return retValue; } public String getMessage() { return "SimpleDice"; …② } }
インターフェースであるIDiceのメソッドをそれぞれ①②で実装しています。①ではJavaランタイムから乱数を取得し、1から6までの中からランダムに値を返します。②では簡単にSimpleDiceの文字列を返すようにしています。
以上でCDIを使ったサイコロ処理に関する機能は完了なので、最後に画面を作ります。
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>乱数の取得</title> </h:head> <h:body style="font-size: 18px"> #{sample.message}から取得した値<br /> …① #{sample.nextValue()} …② </h:body> </html>
①②ともsampleから値を取得しています。このsampleはManagedBeanのvalue属性で定義した名称です。
①でメッセージを、②でサイコロの結果を表示します。
以上の実装が終わりましたらコンテナへ搭載し実行します。この実行結果は次のようになります。
ブラウザの再読み込みを行うことでランダムに1から6の値が表示されることも確認できます。CDIを使った簡単なインスタンス取得の方法はこれだけで完了します。