DI+AOPを実現するSeasarV2:Seaser Projectの全貌を探る(2)(2/3 ページ)
Seasar(シーサー)は、国内のコミュニティ「The Seasar Project」によって開発が行われているオープンソースプロダクトだ。DI+AOPコンテナとして評価が高いSeasarV2は、J2EE開発の現場にも影響力を持ち始めた。例えば電通国際情報サービスがSeasar Projectを正式に支援することを表明し、2005年6月からは同社による商用サポートサービスが開始されている。本連載では、同プロジェクトの代表的なプロダクト紹介していく。(編集局)
DIの作成例
それでは実際の作成例を見てみましょう。ここでは2次元の図形の面積を計算するアプリケーションを、それぞれのDIの方法に合わせて3種類作成しました。あらかじめ、どのアプリケーションでも共通する、面積を求めるメソッドをインターフェイスとして作成してあります(リスト1)。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
コンストラクタ・インジェクションの作成例
最初にコンストラクタ・インジェクションの作成例からです。リスト2は三角形の面積を求めるJavaプログラムで、リスト1のインターフェイスを実装しています。面積を求めるには、底辺と高さの値が必要です。そしてこのプログラムでは図形の名称も登録できるようにしてあります。これらの値はコンストラクタで設定できるようになっています。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
底辺や高さの実際の値は、diconファイル内に、以下のようなコンポーネント定義として記述しておきます。そうするとS2のDIコンテナからリスト2のインスタンスを取得する際に、上記のコンストラクタを用いてリスト2に値が設定されます。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
<component>〜</component>は、コンテナから取得するオブジェクトを表します。class属性にクラスのフルパッケージ名を記述します。<arg>〜</arg>がコンストラクタに設定する引数の値を表しますが、このとき記述する引数の順はソースコードに記述された引数の順に合わせる必要があります。リスト2はコンストラクタの引数が図形の名称、底辺、高さの順ですので、diconファイルの方もそれに合わせてあります。
注意 diconファイルで文字列の値を記述する際の注意
文字列の値(String型の定数)を記述する際には、必ず定数の両端を二重引用符(")で囲まなくてはなりません。二重引用符で囲まれていない文字列が記述されていた場合、diconファイルでは<component>タグのname属性の値が指定されたものとして認識されます。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
セッター・インジェクションの作成例
セッター・インジェクションは、値の設定をsetter(セッター)メソッドを使って行うものです。今度は円の面積を求めるJavaプログラム(リスト3)を例に示します。円の面積を求めるためには半径と円周率の値が必要です。setterメソッドは以下のように作成しました。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
setName、setRadius、setPiという、それぞれのsetterメソッドの存在によって、コンテナでは、リスト3のインスタンスがname、radius、piというプロパティを持っていると認識されます。リスト3の内部でどのような名前の変数が用いられているかは関係ありません。
diconファイルでの設定は以下のようになります。<component>〜</component>間は先ほどと同じですが、セッター・インジェクションの場合は<property>〜</property>を用いて値を設定します。このタグのname属性はsetterメソッドで示されたプロパティ名を記述します。例えば<property name="name">〜</property>には、setNameメソッドで設定する値を記述します。ですから、プロパティの名称さえ間違えていなければ、diconファイルで記述される順とJavaソースコードで記述される順とが異なっていても適切に処理されます。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
メソッド・インジェクションの作成例
S2においてDIを行う方法の最後はメソッド・インジェクションです。これはsetter以外のメソッドで値を設定したいときに用いる方法です。通常は先述した2つの方法で事足りるのですが、何らかの事情でそれ以外のメソッドによるDIが必要になる場合に用います。
値の設定に用いているメソッドは、長方形の面積を求めるJavaプログラム(リスト4)のsetName、 setBaseAndHeightの2つです。これらのメソッドでは、図形の名称と面積の計算に必要な底辺と高さを設定できるようにしてあります。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
diconファイルでの記述は、以下のように<initMethod>〜</initMethod>を用います。このとき、name属性でメソッド名を記述してもよいですし、OGNL(http://www.ognl.org/)式で直接メソッドの実行を指示することもできます。#selfはOGNL式でそのクラス自身を表します。
OGNL(Object-Graph Navigation Language)は式言語の一種ですが、JSPのそれとは記述方法が異なります。詳細はSeasarプロジェクトのOGNLガイド(http://www.seasar.org/ognl.html)を参照してください。ちなみに、本稿で用いているS2.2.10ではOGNLバージョン2.6.5が用いられています。
メソッドの引数はコンストラクタ・インジェクションの場合と同様に<arg>〜</arg>で表します。引数を記述する順はやはりJavaソースコードと合わせておかなくてはなりません。リスト4で底辺と高さの値を設定するsetBaseAndHeightメソッドの場合は第1引数が底辺、第2引数が高さですので、diconファイルでも先に底辺、次に高さの値を記述しています。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
コンテナによるインスタンスの生成(プログラムの実行)
ここまでで3つのDIの方法を紹介してきましたが、それだけではリスト2〜4を実行することはできません。これらのプログラムを実行するには、DIコンテナでインスタンスを生成してもらう必要があります。例えばリスト2を実行するには、以下のようにします。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
リスト2のインスタンスを生成するのはS2Containerクラスですが、これ自体のインスタンスはS2ContainerFactoryクラスのcreateメソッドで生成してもらいます。このとき、引数としてdiconファイルのパスが必要です。
こうして生成されたS2Containerインスタンスを用いて、diconファイルによる定義を加味したリスト2のインスタンスを生成します。このとき、同じインターフェイスを持つクラスがほかになければ、getComponent( Area.class )というように、引数に直接インターフェイスを設定しても良いのですが、リスト2〜4に関する定義をすべて同じdiconファイルに記述してしまうと、S2Containerがどのコンポーネントを用いればよいか分からず、エラーとなってしまいます。そういう場合には、<component>タグのname属性に記述した名称で、インスタンスを生成してほしいクラスを指定します。
diconファイルの記述も、先述の分だけではなく、複数のコンポーネント定義を<components>〜</components>タグで囲み、xml宣言やDOCTYPE宣言を追加して、全体で1つのXMLデータとなるようにします。結果としてdiconファイルの全体像は以下のようになります。
<include>タグは、別のdiconファイルに記述してある定義を読み込んで利用するためのタグです。データベース接続を行う場合など、同じ設定を複数のdiconファイルで共有する場合に用いられます。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
この項の最後に、リスト2〜4までを実行するプログラム(リスト5)とその実行結果を掲載します。ちなみに実行結果に表示されている“cm^2”は平方センチメートルを表します。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
Copyright © ITmedia, Inc. All Rights Reserved.