Seasar DI Container with AOP

OGNLガイド

目次

概要

OGNL (Object Graph Navigation Language) は,Javaオブジェクトのプロパティにアクセスしたりメソッドを呼び出したりすることの出来る,Javaによく似た式言語です.
Seasar2では,diconファイルの<property>要素の他,<component>要素・<initMethod>要素・<destroyMethod>要素・<arg>要素・<meta>要素にOGNL式を記述することが出来ます.
OGNLの詳細はこちらを参照してください.

リテラル

Java標準のリテラル

OGNLでは,Java言語で定められているリテラルをそのまま記述することが出来ます.

true boolean
false
10 int
0xABCD
100L long
1.0 float
0.5F
0.01D double
'A' char
'\uFFFF'
"seasar2" java.lang.String
null 参照型

文字列を記述する際には,ダブルクォーテーションが必要なことに注意してください.

<component class="Person">
    <property name="name">"Taro Yamada"</property>
    <property name="age">25</property>
</component>

OGNL独自のリテラル

OGNL独自のリテラルも用意されています.
java.math.BigDecimalおよびjava.math.BigIntegerを表すリテラルがあります.

100.00B java.math.BigDecimal
100000H java.math.BigInteger

定義済みオブジェクト

diconファイルに記述されたOGNL式は,S2コンテナが用意したコンテキストで実行されます.
この実行コンテキストには,次のオブジェクトがあらかじめ定義されています.

名前 説明
container org.seasar.framework.container.S2Container 現在のdiconファイルを処理しているS2コンテナです.
request javax.servlet.http.HttpServletRequest Webコンテナ上で実行されている場合,現在のスレッドで処理しているリクエストです.
設定されていない場合もあります.
response javax.servlet.http.HttpServletResponse Webコンテナ上で実行されている場合,現在のスレッドで処理しているレスポンスです.
設定されていない場合もあります.
session javax.servlet.http.session.HttpSession Webコンテナ上で実行されている場合,現在のスレッドで処理しているセッションです.
設定されていない場合もあります.
servletContext javax.servlet.ServletContext Webコンテナ上で実行されている場合,現在のS2コンテナに関連づけられたサーブレットコンテキストです.
設定されていない場合もあります.

さらに,コンテナに登録されているコンポーネントをその名前 (name属性の値) で参照することが出来ます.

変数

OGNLは変数を使うことが出来ます.全ての変数はグローバルで,先頭に'#'を付けます.
変数の設定はJava言語と同様,=演算子を使って値を代入しますが,diconファイルの中で変数を設定することはあまりないでしょう.

定義済みの変数

変数 説明
#this この変数を含んだ式の「現在のオブジェクト」を表します.
#self <initMethod>または<destroyMethod>のボディの中でのみ定義されている変数です.
この変数は,現在のコンポーネント (<initMethod>または<destroyMethod>を囲む<component>要素で表されているオブジェクト) を参照します.

オブジェクトの生成

オブジェクトを生成するには,Java言語の場合と同様にnew演算子を使用します.クラス名はパッケージ名で修飾した完全限定名で指定する必要があります (java.langパッケージの場合は省略することが出来ます).

<property name="url">new java.net.URL("http://localhost/")</property>

配列を生成することも出来ます.

<property name="array1">new int[5]</property><!-- 配列の要素はすべて0 -->
<property name="array2">new int[] {1, 3, 5}</property>

java.uti.ArrayListのインスタンスを手軽に生成することも出来ます.ただし,具体的な実装型 (java.util.LinkedListなど) は指定することが出来ません.

<property name="list">{"green", "red", "blue"}</property>

java.util.Mapのインスタンスを手軽に生成することも出来ます.

<property name="map">#{"key1" : "value1", "key2" : "value2", "key3" : "value3"}</property>

java.util.Mapの実装型を指定することも出来ます (省略時はjava.util.LinkedHashMapになります).

<property name="map">#@java.util.TreeMap@{"key1" : "value1", "key2" : "value2"}</property>

フィールドへのアクセス

オブジェクトのpublicなフィールドへアクセスすることが出来ます.

インスタンスフィールド

インスタンスフィールドは,Java言語と同じようにアクセスすることが出来ます.

<property name="x">point.x</property>

staticフィールド

staticフィールドにアクセスするには,クラス名の前後を'@'で囲んで,その後にフィールド名を記述します.クラス名はパッケージ名で修飾した完全限定名を指定する必要があります (java.langパッケージの場合は省略することが出来ます).

<property name="priority">@Thread@NORM_PRIORITY</property>

メソッドの呼び出し

オブジェクトのpublicなメソッドを呼び出すことが出来ます.

インスタンスメソッド

インスタンスメソッドは,Java言語と同じように呼び出すことが出来ます.

<property name="files">dir.listFiles()</property>

staticメソッド

staticメソッドを呼び出すには,クラス名の前後を'@'で囲んで,その後にメソッド名を記述します.クラス名はパッケージ名で修飾した完全限定名を指定する必要があります (java.langパッケージの場合は省略することが出来ます).

<property name="roots">@java.io.File@listRoots()</property>

プロパティへのアクセス

OGNLを使用する上で中心となるのがプロパティへのアクセスです.

JavaBeansのプロパティ

OGNLでは,JavaBeansにおけるプロパティ (getter/setterメソッドでアクセスできるもの)を扱うことが出来ます.
次の例では,helloという名前の付けられたコンポーネントのmessageというプロパティ値をコンポーネントとして定義しています.messageプロパティの値は,examples.dicon.HelloSetterInjectionクラスのgetMessage()メソッドが返す値です.

<component name="hello" class="examples.dicon.HelloSetterInjection">
    <property name="message">"Hello World!"</property>
</component>

<component name="msg">
    hello.message
</component>

Mapのエントリ

java.util.Mapのエントリもプロパティとして扱うことが出来ます.この場合,キーがプロパティ名となります.ただし,プロパティ名として使うことが出来るのは,識別子として有効なjava.lang.String型のキーだけです.
次の例では,コンポーネントoneはコンポーネントmapのキーoneに関連づけられている値1B (java.math.BigDecimalの1) になります.

<component name="map">
    #{"one" : 1B, "two" : 2B, "three" : 3B}
</component>

<component name="one">
    map.one
</component>

コンポーネント

コンテナに登録されているコンポーネントをプロパティとして扱うことが出来ます.この場合,コンポーネントの名前 (name属性の値) がプロパティ名となります.

<component name="foo" class="Foo"/>

<component name="">
    <property name="foo">container.foo</property>
</component>

インデックスによるアクセス

Javaの配列

Javaの配列はJavaと同じようにアクセスすることが出来ます.
次の例では,java.io.File#listRoots()メソッドが返す配列の最初の要素がプロパティに設定されます.

<property name="root">@java.io.File@listRoots()[0]</property>

JavaBeansのインデックス付きプロパティ

JavaBeansのインデックス付きプロパティを配列のように扱うことが出来ます.
次の例では,org.seasar.framework.container.S2Container#getChild(int)が呼び出されます.

<property name="firstChild">container.child[0]</property>

連想配列

プロパティやフィールドを連想配列のようにアクセスすることが出来ます.
次の例では,org.seasar.framework.container.S2Container#getNamespace()が呼び出されます.

<property name="tm">container["namepace"]</property>

連想配列によるインデックス付きプロパティ

JavaBeansのインデックス付きプロパティの拡張として,任意の型をインデックスとするプロパティにアクセスすることが出来ます.
次の例では,org.seasar.framework.container.S2Container#getComponentDef(String)が呼び出されます.

<property name="tm">container.componentDef["j2ee.transactionManager"]</property>

コレクションの操作

in 演算子

in演算子を使うことで,配列またはコレクション (java.util.Collectionのインスタンス) に要素が含まれているかをテストすることが出来ます.
次の例では,colorというコンポーネントが"red""green""blue"の中に含まれているかをテストしています.colorの値は"red"であるため,コンポーネントcontainstureになります (実際にはbooleanのラッパー型であるBoolean型になります).

<component name="color">"red"</component>

<component name="contains">color in {"red", "green", "blue"}</component>

セレクション

配列またはコレクションから,条件にマッチする要素だけを選択することが出来ます.
次の例では,リストcolorsから,3文字より長い要素だけを選択したリスト (要素は "green""blue") がコンポーネントselectedになります.
#thisは配列またはコレクションの各要素への参照です.

<component name="colors">{"red", "green", "blue"}</component>

<component name="selected">colors.{? #this.length() > 3}</component>

条件にマッチする最初の要素だけを選択することも出来ます.
次の例では,コンポーネントfirstMatch"green"になります.

<component name="colors">{"red", "green", "blue"}</component>

<component name="firstMatch">colors.{^ #this.length() > 3}</component>

条件にマッチする最後の要素だけを選択することも出来ます.
次の例では,コンポーネントlastMatch"blue"を唯一の要素とするリストになります.

<component name="colors">{"red", "green", "blue"}</component>

<component name="lastMatch">colors.{$ #this.length() > 3}</component>

プロジェクション

配列またはコレクションの各要素に対して,そのプロパティまたはメソッドを適用した戻り値からなるコレクションを作ることも出来ます.
次の例では,様々な型の数値からなるリストnumbersから,その文字列表現を要素とするリストstringsを作成しています.

<component name="numbers">{0, 1L, 2.5f, 3B}</component>

<component name="strings">numbers.{#this.toString()}</component>

カンマ演算子とチェーン

カンマ演算子を使うと,複数の副式を続けて記述することが出来ます.最後の副式の値が式全体の結果となります.
次の例では,標準出力へのプリントと,fooというオブジェクトの参照という二つの副式が記述されています.式全体の結果は最後の副式であるfooになります.

<property name="foo">@System@out.println("Foo:" + foo), foo</property>

同一オブジェクトに対するメソッドを繰り返し呼び出す場合などに便利な記述方法が用意されています.
次の例では,<initMethod>要素の中で#self (HashSetのインスタンス) に対するadd()メソッドの呼び出しを3回繰り返しています.add()メソッドは,それを囲んでいるカッコで区切られたコンテキストで評価されます.このコンテキストは#self (HashSet)であるため,どのadd()メソッドの呼び出しもHashSetに対して行われます.

<component name="set" class="java.util.HashSet">
    <initMethod>#self.( add("one"), add("two"), add("three") )</initMethod>
</component>