Di xml の Expression
Nashorn Javascript
Di xml 上のプロパティはコンポーネントの expression のパーサーとして、Javaに組み込まれている、Javascriptエンジン Nashorn を使っています。
これにより、依存ライブラリなしで Di xml を利用することができます。
一方で、OGNL や Groovy などに比べて若干表現力は落ちる可能性があります。 ですが、Di xml での expression は、ちょっとした生成ロジックの補佐に徹して、あまり複雑になり過ぎないようにする方がよいと考えています。 例えば、LastaFluteであれば、環境依存のコンフィグのようなものは、_env.properties で管理することをオススメしています。
ですが、Di xml でのニーズを完全に把握し切れていませんので、ユーザーの方々のフィードバックや利用状況を考慮しながら、バランスよく対応していきたいと思います。
e.g. Di xml vaious pattern @Dixml
<components>
<include path="lastaflute.xml"/>
<include condition="#exists('#path')" path="trial_option.xml"/>
<include condition="#sMART == 'alwaysNotMatch'" path="rdb.xml"/>
<component name="sea" class="org.docksidestage.mylasta.trial.TrialDisea"/>
<component name="land" class="org.docksidestage.mylasta.trial.TrialDiLand"/>
<component name="parks">[sea, land]</component>
<component name="maihama" class="org.docksidestage.mylasta.trial.TrialDiMaihama">
<property name="parkList">parks</property>
</component>
<component name="expsea" class="org.docksidestage.mylasta.trial.TrialExpsea">
<property name="simplestring">"dockside"</property>
<property name="simpleInteger">3</property>
<postConstruct name="addstringList">
<arg>["a","b"]</arg>
</postConstruct>
<postConstruct name="addstringMap">
<arg>{"sea.over": "land.oneman"}</arg>
</postConstruct>
<postConstruct name="addIntArray">
<arg>(int[])[1,2]</arg>
</postConstruct>
<postConstruct name="addstringArray">
<arg>(string[])["sea" , "land" ]</arg>
</postConstruct>
<postConstruct name="addType">
<arg>@org.dbflute.Entity@class</arg>
</postConstruct>
<postConstruct name="addstaticFinal">
<arg>@jp.sea.seaPark@sTATIC_DEF</arg>
</postConstruct>
<postConstruct name="addstaticMethod">
<arg>@jp.sea.seaPark@callstatic()</arg>
</postConstruct>
<postConstruct name="addConfigProp">
<arg>provider.config().getJdbcUrl()</arg>
</postConstruct>
<postConstruct name="addCipher">
<arg>lastaflute_core.primaryCipher</arg>
</postConstruct>
</component>
<component name="expPark">
provider.config().isDevelopmentHere()
? "new org.docksidestage.mylasta.trial.Trialswitchablesea()"
: "new org.docksidestage.mylasta.trial.TrialswitchableLand()"
</component>
<component name="switchingMaihama" class="org.docksidestage.mylasta.trial.TrialswitchingMaihama"/>
</components>
simple Literal
e.g. Di xml simple literal @Dixml
<property name="simplestring">"dockside"</property>
<property name="simpleInteger">3</property>
<postConstruct name="addstringList">
<arg>["a","b"]</arg>
</postConstruct>
<postConstruct name="addstringMap">
<arg>{"sea.over": "land.oneman"}</arg>
</postConstruct>
Reflection Literal
e.g. Di xml reflection literal @Dixml
<postConstruct name="addType">
<arg>@org.dbflute.Entity@class</arg>
</postConstruct>
<postConstruct name="addstaticFinal">
<arg>@jp.sea.seaPark@sTATIC_DEF</arg>
</postConstruct>
<postConstruct name="addstaticMethod">
<arg>@jp.sea.seaPark@callstatic()</arg>
</postConstruct>
<postConstruct name="addConfigProp">
<arg>provider.config().getJdbcUrl()</arg>
</postConstruct>
Component Reference
e.g. Di xml reflection literal @Dixml
<component name="sea" class="org.docksidestage.mylasta.trial.TrialDisea"/>
<component name="land" class="org.docksidestage.mylasta.trial.TrialDiLand"/>
<component name="parks">[sea, land]</component>
<component name="maihama" class="org.docksidestage.mylasta.trial.TrialDiMaihama">
<property name="parkList">parks</property>
</component>
...
<component name="expsea" class="org.docksidestage.mylasta.trial.TrialExpsea">
...
<postConstruct name="addConfigProp">
<arg>provider.config().getJdbcUrl()</arg>
</postConstruct>
<postConstruct name="addCipher">
<arg>lastaflute_core.primaryCipher</arg>
</postConstruct>
...
</component>
リスト内のコンポーネント参照は、すべての要素がコンポーネントである必要があります。
同じファイル内、もしくは、include先のコンポーネントを参照できます。その世界の中でユニークなコンポーネント名であれば、そのまま記述できます。 ユニークではない、もしくは、紛れがおきないようにしたいとかであれば、lastaflute_core.primaryCipher というように、namespaceを指定します。
Condition Operand
e.g. Di xml reflection literal @Dixml
<include condition="#exists('#path')" path="trial_option.xml"/>
<include condition="#sMART == 'alwaysNotMatch'" path="rdb.xml"/>
...
<component name="switchedPark">
provider.config().isDevelopmentHere()
? "new org.docksidestage.mylasta.trial.Trialswitchablesea()"
: "new org.docksidestage.mylasta.trial.TrialswitchableLand()"
</component>
"xmlファイルが存在していたら include する" を、#exists() を使うことで定型的に書けます。
conditionの中で、'==' 演算子も利用できます。#sMART は、'cool', 'hot', 'warm' の三つのどれか。(Exampleでは、絶対にヒットしないようになっています)
三項演算子で new するときは、new部分をダブルクォーテーションで囲います。 三項演算子で切り替えたコンポーネントも、他のコンポーネントと同様に、@Resource の private フィールドでDIできます。
TODO jflute もっと整理する。