Seasar DI Container with AOP

クイックスタート

S2Containerは、Dependency Injection(以降DIと略します)をおこなう軽量コンテナです。 EJB3も実装しています。

最初の一歩

早速試してみましょう。登場人物は次のようになります。

  • あいさつクラス
    • あいさつ用の文字列を返す。
  • あいさつクライアントクラス
    • あいさつクラスから取得したあいさつ(文字列)をコンソールに出力する。
  • あいさつメインクラス
    • 起動用のクラス。あいさつクラスとあいさつクライアントクラスの組み立ても行う。
Greeting.java

あいさつのためのインターフェースです。

package examples.ejb3;

public interface Greeting {

    String greet();
}
GreetingImpl.java

あいさつの実装です。Statelessアノテーションを使って、簡単にStateless SessionBeanを作ることができます。

package examples.ejb3.impl;

import javax.ejb.Stateless;

import examples.ejb3.Greeting;

@Stateless
public class GreetingImpl implements Greeting {

    public String greet() {
        return "Hello World!";
    }
}
GreetingClient.java

あいさつを利用するクライアントのインターフェースです。

package examples.ejb3;

public interface GreetingClient {

    void execute();
}
GreetingClientImpl.java

あいさつを利用するクライアントの実装です。 EJBアノテーションを使って、Greetingインターフェースを実装したSessionBeanを参照することができます。

package examples.ejb3.impl;

import javax.ejb.EJB;
import javax.ejb.Stateless;

import examples.ejb3.Greeting;
import examples.ejb3.GreetingClient;

@Stateless
public class GreetingClientImpl implements GreetingClient {

    @EJB
    private Greeting greeting;

    public void execute() {
        System.out.println(greeting.greet());
    }
}
GreetingMain.dicon

EJB3用の設定ファイルです。 この内容を最初に記述しておけば、後からEJBが増えても、ファイルに情報を追加する必要はありません。 詳しくは、コンポーネントの自動登録を参照してください。

<components>
<include path="ejb3tx.dicon"/>
<component
class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
<initMethod name="addClassPattern">
<arg>"examples.ejb3.impl"</arg>
<arg>".*Impl"</arg>
</initMethod>
</component>
</components>
GreetingMain.java

Seasar2のEJB3を実行するためのコードは次のようになります。 SingletonS2ContainerFactoryについての詳細はS2Containerの生成を参照してください。 @EJBのname属性を指定しなかった場合の、デフォルトの名前の命名規則は、DefaultAutoNamingを参照してください。

package examples.ejb3.main;

import javax.naming.Context;
import javax.naming.InitialContext;

import org.seasar.framework.container.factory.SingletonS2ContainerFactory;

import examples.ejb3.GreetingClient;

public class GreetingMain {

    private static final String PATH = "examples/ejb3/dicon/GreetingMain.dicon";

    public static void main(String[] args) throws Exception {
        SingletonS2ContainerFactory.setConfigPath(PATH);
        SingletonS2ContainerFactory.init();
        try {
            doMain(args);
        } finally {
            SingletonS2ContainerFactory.destroy();
        }
    }

    public static void doMain(String[] args) throws Exception {
        Context ctx = new InitialContext();
        GreetingClient greetingClient = (GreetingClient)
            ctx.lookup("greetingClient");
        greetingClient.execute();
    }
}

実行結果は下記のようになります。

DEBUG 2006-03-25 18:38:47,892 [main] トランザクションを開始しました
Hello World!
DEBUG 2006-03-25 18:38:47,922 [main] トランザクションをコミットしました

EJB3アノテーションリファレンス

S2Containerでは、EJB 3.0 Simplified APIのアノテーションもサポートしています。EJB3アノテーションを利用するにはJava5(Tiger)が必要です。

Statelessアノテーション

Statelessアノテーションを使って、Stateless SessionBeanを定義します。

Tigerアノテーションは以下のようになります。name属性を省略した場合、 コンポーネントの自動登録で使われるAutoNamingの実装クラスによって、 名前が自動的に決められます。

@Stateless(name="xxx")
public class Xxx {
    ...
}

Statefulアノテーション

Statefulアノテーションを使って、Stateful SessionBeanを定義します。

Tigerアノテーションは以下のようになります。name属性を省略した場合、 コンポーネントの自動登録で使われるAutoNamingの実装クラスによって、 名前が自動的に決められます。

@Stateful(name="xxx")
public class Xxx {
    ...
}

EJBアノテーション

EJBアノテーションによって、EJB3コンポーネントを参照することができます。 Statless、Statefulアノテーションのname属性で付けた名前をbeanName属性に指定することができます。 beanName属性は、インターフェースを実装したオブジェクトが複数存在する場合にのみ使うようにしてください。

EJBアノテーションはフィールドまたはsetterメソッドに指定することができます.フィールドに指定された場合でbeanName属性が指定されなかった場合は,フィールド名がEJB3コンポーネント名として使用されます.

@EJB
private Aaa aaa;

@EJB(beanName="bbb2")
public void setBbb(Bbb bbb) {
    ...
}

Resourceアノテーション

Resourceアノテーションによって、DataSourceやDAO等のコンポーネントを参照することができます。 コンポーネントの名前をname属性に指定することができます。 name属性は、インターフェースを実装したオブジェクトが複数存在する場合にのみ使うようにしてください。

Resourceアノテーションはフィールドまたはsetterメソッドに指定することができます.フィールドに指定された場合でname属性が指定されなかった場合は,フィールド名がコンポーネント名として使用されます.

@Resource
private EmployeeDao employeeDao;

@Resource(name="fooDataSource")
private void setDataSource(DataSource ds) {
    ...
}

TransactionManagementアノテーション

TransactionManagementアノテーションにより、コンテナ管理トランザクション(CMT)とBean管理トランザクション(BMT)を使い分けることができます。
デフォルトはCMTであるため、CMTを使用する場合はTransactionManagementアノテーションを明示する必要はありません。

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class Xxx {
    ...
}

TransactionAttributeアノテーション

TransactionAttributeアノテーションにより、ビジネスメソッドのトランザクション属性を設定することができます。この指定が有効なのは、CMTの場合のみです。
クラスにTransactionAttributeアノテーションを付けることにより、そのクラスのビジネスメソッド全体のトランザクション属性を設定することができます。指定しなかった場合のデフォルトはREQUIREDです。
メソッドにTransactionAttributeアノテーションを付けることにより、そのビジネスメソッドのトランザクション属性を設定することができます。指定しなかった場合のデフォルトはクラスに付けられたトランザクション属性です。
TransactionAttributeアノテーションを使用するには、そのセッションビーンを登録するコンテナにejb3tx.diconをインクルードする必要があります。 ejb3tx.diconはS2Tigerのresourcesディレクトリの下にあります。

@Stateless
@TransactionAttribute(TransactionAttributeType.MANDATRY)
public class Xxx {
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void someMethod() {
        ...
    }
}

Interceptorsアノテーション

Interceptorsアノテーションにより、ビジネスメソッドの呼び出しやライフサイクルイベントをインターセプトするクラスを複数指定することができます。
Interceptorsアノテーションはクラスまたはメソッドに付けることができます。

@Stateless
@Interceptors({foo.bar.HogeInterceptor.class, foo.bar.SomeInterceptor})
public class Xxx {
    ...
    @Interceptors(foo.bar.MethodInterceptor)
    private void hogehoge() {
        ...
    }
}

ExcludeClassInterceptorsアノテーション

ExcludeClassInterceptorsアノテーションにより、クラスに@Interceptorsアノテーションで指定したインターセプタをメソッドに適用しないことを指定することができます。

@Stateless
@Interceptors(foo.bar.HogeInterceptor.class)
public class Xxx {
    ...
    @ExcludeClassInterceptos
    @Interceptors(foo.bar.MethodInterceptor)
    private void hogehoge() {
        ...
    }
}

PostConstructアノテーション

PostConstructアノテーションにより、インスタンス生成~DIの後に呼び出されるメソッドを指定することができます。
PostConstructアノテーションはセッションビーンまたはインターセプタクラスのメソッドに指定することができます。
セッションビーンにPostConstructアノテーションを付ける場合、そのメソッドは非static、非finalで引数がなく、戻り値型がvoidでなければなりません。メソッド名および可視性は任意です。
インターセプタにPostConstructアノテーションを付ける場合、そのメソッドは非static、非finalで引数はjavax.interceptor.InvocationContext型一つだけ、戻り値型がvoidでなければなりません。メソッド名および可視性は任意です。

@Stateless
@Interceptors(Yyy.class)
public class Xxx {
    ...
    @PostConstruct
    private void initialize() {
        ...
    }
}

public class Yyy {
    ...
    @PostConstruct
    private void initialize(InvocationContext context) {
        ...
    }
}

AroundInvokeアノテーション

AroundInvokeアノテーションにより、ビジネスメソッドの呼び出しをインターセプトすることができます。
AroundInvokeアノテーションはセッションビーンまたはインターセプタクラスのメソッドに指定することができます。
セッションビーンにAroundInvokeアノテーションを付けることができるメソッドは非static、非finalで引数はjavax.interceptor.InvocationContext型一つだけ、戻り値型はjava.lang.Object型でなければなりません。メソッドの名前や可視性は任意です。
クラスで一つのメソッドにだけAroundInvokeアノテーションを付けることができます。

@Stateless
@Interceptors(Yyy.class)
public class Xxx {
    ...
    @AroundInvoke
    private Object invoke(InvocationContext context) throws Exception {
        ...
    }
}

public class Yyy {
    ...
    @AroundInvoke
    Object invoke(InvocationContext context) throws Exception {
        ...
    }
}