Seasar2のDIContainerを使ったコンポーネントとアスペクトの自動バインディング

Seasar2+S2Daoでバッチアプリケーションを作っています。   ■ 流れ 1. ジョブスケジューラ  ↓ 2. シェル(パス通したり)  ↓ 3. Java(Main文持ってる。DIContainerの起動とか、パラメータの解釈とか。)  ↓ 4. 各ビジネスロジック(Dao使ってDBアクセスしたりとか、イロイロ。)   ■ パッケージの構成(普通のMavenプロジェクト) src/main/java - hoge.dao - hoge.entity - hoge.job - hoge.xxx src/main/resources - aop.dicon - app.dicon - j2ee.dicon ※ dao.diconはs2-dao-.jarに内包されている   ■ Jobクラス Jobの構成 - AbstractJob…親クラス。 - HogeJob…ビジネスロジックを実行するクラス。   上記について、HogeJobをシェルからの引数で渡してインスタンスを起動したいので、 以下のように設定すると、勝手に探してくれてバインディングしてくれます。 addClassPatternが追加したいクラスのパッケージとクラスで addIgnoreClassPatternがシカトしたいクラスのパッケージとクラスです。 今回はAbstractのインスタンスは要らないのでシカトに設定します。

<!-- Auto Binding(Job without AbstractJob) -->
<component
 class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
 <property name="autoNaming">
  <component class="org.seasar.framework.container.autoregister.DefaultAutoNaming"/>
 </property>
 <initMethod name="addClassPattern">
  <arg>"hoge.job"</arg>
  <arg>".*Job"</arg>
 </initMethod>
 <initMethod name="addIgnoreClassPattern">
  <arg>"hoge.job"</arg>
  <arg>"AbstractJob"</arg>
 </initMethod>
</component>

こうすることによって"hogeJob"をMainメソッドの第一引数に渡してあげれば、 コンテナを起動した後に引数で指定した名前(コンポーネント名はデフォルトでクラス名の先頭文字が小文字になる)で HogeJobのメソッドを走らせる事が出来ます。

〜略〜
String jobName = args[0];
〜略〜
SingletonS2ContainerFactory.setConfigPath("app.dicon");
SingletonS2ContainerFactory.init();
container = SingletonS2ContainerFactory.getContainer();
〜略〜
job = (AbstractJob)container.getComponent(jobName);
job.execute(parameters);
〜略〜

  ■ Daoクラス S2JDBCを使うか迷ったのですが、既存サービスのスキーマ定義が独特だったり、 開発プロセス的にもテーブル定義を頻繁に変更出来ないので 業務ドメインとテーブルモデルは切り離した方がよさそうに思ったのでS2Daoにしました。 ↓読んで、そんな解釈をしました。。 http://d.hatena.ne.jp/higayasuo/20080201/1201858270   前置きはそれくらいにして、、 ここでも自動バインディングを使うことでいちいちdiconファイルをあーだこーだしなくてもいいような形にします。 S2Daoは↓こんな感じでinterfaceで定義するので、上記のJobのようにコンポーネントの自動登録だけって わけにはいきません、と。

@S2Dao(bean = Employee.class)
public interface EmployeeDao {
 public int selectCountAll();
}

で、どうするかと言うと、以下のように(ちょっと長いですが…)、AspectAutoRegisterというのを使います。

<!-- Auto Binding(Dao) --> 
<component
  class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
  <property name="autoNaming">
   <component class="org.seasar.framework.container.autoregister.DefaultAutoNaming"/>
  </property>
  <initMethod name="addClassPattern">
   <arg>"hoge.dao"</arg>
   <arg>".*Dao"</arg>
  </initMethod>
 </component>
<component class="org.seasar.framework.container.autoregister.AspectAutoRegister">
  <property name="interceptor">dao.interceptor</property>
  <initMethod name="addClassPattern">
    <arg>"hoge.dao"</arg>
     <arg>".*Dao"</arg>
  </initMethod>
</component>

interceptorのdao.interceptorってなんじゃらホイ?って思ってたら、 dao.dicon(s2-dao-.jarに内包されている)に↓のように定義されていました。 特にPager機能を使う予定もないのですが、まぁDaoが動いてくれればいいかな、と。

<components namespace="dao">
~略~
 <component
  name="interceptor"
  class="org.seasar.dao.pager.PagerS2DaoInterceptorWrapper">
  <arg>
   <component class="org.seasar.dao.interceptors.S2DaoInterceptor"/>
  </arg>

あとDao系だと、FechHandler(http://s2dao.seasar.org/ja/s2dao-tiger.html#FetchHandler)使おうとか。   ■ JobクラスへのDaoのインジェクション Jobクラスの中ではDaoクラスを使うわけですが、以前のプロジェクトではsetter injectionを使っていました。が、 ↓のようにpublicなプロパティを用意しておくだけで、勝手にセットしてくれます。ゴイスー。

public class SampleJob extends AbstractJob{
 public EmployeeDao employeeDao; ★ ココにインジェクションしてくれる ★
 protected void execute(String to) throws Exception {
  System.out.println(employeeDao.selectCountAll());
 }
}

  ■ 便利ツール ちゃんと狙ったのがバインディングされているかどうか知りたい場合に ↓のブログに記載されている以下のコードがとても便利でした。ありがとうございました。 http://snowhiro.web.fc2.com/seasar2/seasar2_03_AOP_04.html

for (int i = 0; i < container.getComponentDefSize(); i++) {
 String compName = container.getComponentDef(i).getComponentName();
 Class className = container.getComponentDef(i).getComponentClass();
 if (compName != null && className != null) {
  System.out.println("コンポーネント名 : " + compName + " : クラス名 : "
    + className.toString());
  int aopSize = container.getComponentDef(i).getAspectDefSize();
  for (int j = 0; j < aopSize; j++) {
   System.out.println(" AOP : "
     + (j + 1)
     + " : "
     + container.getComponentDef(i).getAspectDef(j)
       .getAspect().getMethodInterceptor()
       .getClass().getName());
  }
 }
}

  ■ なんだか、、 何年間ちゃんと追ってなかったのかバレそうな感じですが、 他にもs2csv(http://s2csv.sandbox.seasar.org/)とか バッチで使うのに便利そうなのありますね。 普段からアンテナ立てとかないとイカンなぁ…。  

Seasar 2 徹底入門 SAStruts/S2JDBC 対応
竹添 直樹
翔泳社
売り上げランキング: 7030

 

オープンソース徹底活用 Slim3 on Google App Engine for Java
ひが やすを 小川 信一
秀和システム
売り上げランキング: 28515