Seasarにさわるさー

作成 2004/10/9

巷で話題のSeasarにさわってみます。

Seasarって?

Seasarはオープンソースの国産DIコンテナです。

Seasarプロジェクト
http://www.seasar.org/

DIコンテナの中には、設定ファイルの記述が複雑で、ちょっとしたインジェクションを行うだけでも骨が折れるものがありますが、Seasarは「非常に簡単」に利用することができます。あまり利用されない機能を省き、必要な機能を少ない設定で実現することができます。Seasarは国産のプロジェクトで、ドキュメントが読みやすいのも「簡単」と思える理由の1つかもしれません。

既に分かりやすい日本語ドキュメントがあるので、このページの存在価値はあまりありませんが、まあ、僕もさわってみたよ、ということでメモっときます。

Seasarを使ってみる

ダウンロード

プロジェクトのWebサイトからSeasarをダウンロードします。ここでは現在の最新版のS2.0.22.zipをダウンロードしました。

環境設定

ダウンロードしたファイルを展開し、libディレクトリの中のJARをクラスパスに通します。全て通してもいいですが、最低限必要なJARは以下になります。

aopalliance.jar
asm.jar
cglib-2.0.jar
log4j-1.2.8.jar
ognl-2.6.5.jar
s2-framework-2.0.22.jar

DIコンテナを使う

Seasarでは、XMLの設定ファイル(diconファイルと呼ばれます)にコンポーネント情報を記述します。

まず次のようなクラス/インターフェイスがあるとします。

IFoo.java

package bean;

public interface IFoo {
    void doSomething();
}

Foo.java

package bean;

public class Foo implements IFoo{

    private String message = "";
    
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }

    public void doSomething() {
        System.out.println("doSomething " + message);
    }
}

このクラスをdiconファイルに登録します。ここではbean.Fooクラスをfooという名前で登録しています。初期化時に文字列"Hello"をmessageプロパティーにセットしています。

test.dicon

<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
"http://www.seasar.org/dtd/components.dtd">

<components>

    <component name="foo" class="bean.Foo">
        <property name="message">"Hello"</property>
    </component>

</components>

このfooコンポーネントを呼び出す側は次のようなコードになります。上記設定ファイル、test.diconはクラスパス上のaop/test.diconにあるとします。

package aop;

import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.S2ContainerFactory;

import bean.Foo;

public class Main {

    public static void main(String[] args) {
        S2Container container = S2ContainerFactory.create("aop/test.dicon");
        Foo foo = (Foo)container.getComponent("foo");
        foo.doSomething();
    }

}

実行すると以下のように表示されます。

doSomething Hello

クラスによるコンポーネントの取得

コンポーネントの取得は、名前を引数にとる他にクラス(やインターフェイス)を引数にして取得する方法があります。この場合、指定したクラスを継承、実装するコンポーネントが取得されます。

IFoo foo = (IFoo)container.getComponent(IFoo.class);

同じクラスを複数登録する場合もありますが、多くの場合は、単一のクラスを単一のコンポーネントとして登録して、コンポーネント名=完全クラス名とするパターンも多いと思うので、便利な取得手段でしょう。ただし、指定したクラスが複数登録されている場合は、実行時に例外がスローされます。

AOPを使う

次に上記のコンポーネントにAOPをかけてみましょう。次のクラスは簡単なMethodInterceptorの実装です。メソッド呼び出しの前後で、before、afterと表示しています。

MyIntercepter.java

package aop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyIntercepter implements MethodInterceptor{
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("before");
        Object result = invocation.proceed();
        System.out.println("after");
        return result;
    }
}

このインターセプターをfooコンポーネントに適用します。diconファイルは次のようになります。doSomethingメソッドにmyIntercepterを適用しています。

test2.dicon

<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
"http://www.seasar.org/dtd/components.dtd">

<components>
    <component name="myInterceptor"
        class="aop.MyIntercepter"/>

    <component name="foo" class="bean.Foo">
        <property name="message">"Hello"</property>
        <aspect pointcut="doSomething">myInterceptor</aspect>
    </component>

</components>

呼び出し側は前の例(Main.java)と同じです(が、diconファイルはaop/test2.diconを読み込みます)。実行すると次のように表示されます。

before
doSomething Hello
after

diconファイルを利用しない方法

あまり利用しないかもしれませんが、diconファイルに登録せずに、Javaコード中でプログラム的にAOPを指定する方法も提供されています。

Pointcut pointcut = new PointcutImpl(new String[]{"doSomething"});
Aspect aspect = new AspectImpl(new MyIntercepter(), pointcut);
AopProxy aopProxy = new AopProxy(Foo.class, new Aspect[]{aspect});
Foo foo = (Foo) aopProxy.create();

参考

Seasarのドキュメント
http://homepage3.nifty.com/seasar/document.html

作ったサンプル(JAR抜き)
s1.zip


TOP