インターセプタ

EJB3と同じく、Web Beansではjavax.interceptorパッケージを用いてメソッドインターセプタを作成することができる。EJB3との違いは、@Interceptorsアノテーションではなく、メタアノテーションの仕組みを使用してインターセプタをコンポーネントに関連付けるのが可能な点だ。

たとえば、リスト23のようなインターセプタがあったとする。

リスト23

    @Interceptor
    public class LogInterceptor {
      @AroundInvoke
      public void aroundInvoke(InvocationContext ic) {
        ...
      }
    }

これをクラスに関連付けるには、通常、@Interceptorsアノテーションを使用する。

リスト24

    @Component
    @Interceptors({LogInterceptor.class})
    public class GreetingPrinter {
      ...
    }

Web Beansの提供する枠組みを使用すると、アノテーションを用いてインターセプタのバインドを行うことが可能だ。そのためには、まず@IntercepterBindingTypeを付与したアノテーションを作成する。

リスト25

    @InterceptorBindingType
    @Retention(RUNTIME)
    @Target({TYPE, METHOD})
    public @interface Log {
    }

このアノテーションを、インターセプタにも付与する。これで、インターセプタとアノテーションが関連付けられる。

リスト26

    <strong>@Log</strong>
    @Interceptor
    public class LogInterceptor {
      @AroundInvoke
      public void aroundInvoke(InvocationContext ic) {
        ...
      }
    }

そして、コンポーネントにインターセプタを関連付けるには、作成したアノテーションを付与するだけだ。

リスト27

    @Component
    @Log
    public class GreetingPrinter {
      ...
    }

また、メソッドを限定してインターセプタを適用することも可能だ。

リスト28

    @Component
    public class GreetingPrinter {
      @Log
      public void print() {
        ...
      }
    }

最後に重要なことは、こうして作成したインターセプタはデフォルトでは有効にならないと言うことだ。これらを有効にするには、web-beans.xmlにてインターセプタのクラス名を指定する。

リスト29

    <interceptors>
      <interceptor>examples.Log</interceptor>
      <interceptor>examples.Transactional</interceptor>
    </intercepters>

<intercepters>内には複数のインターセプタを定義できるが、その順序が重要だ。インターセプタの適用順序は、ここに記述した順序に従う。