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 もっと整理する。