EJB 3.0(Public Draft)入門記 Simplified API Chapter3 おまけ

Chapter4に進む前に、@Interceptorが指定されているBeanの内部から同じBeanのビジネスメソッドを呼んだらどうなるかを確かめたいと思います。

コメント欄のひがさんの説明によると、AOP実装にはProxyタイプとByteコード拡張形式があって、Proxyタイプの場合、「同じBeanにメソッドa,bを定義し、a,bにInterceptorを適用し、aからbを呼び出した場合、たぶん、bのInterceptorは動かない」ということです。でおそらくJBossはProxyタイプだろうと。

コードを動かしてみます。いままで使ってきたCalculatorインタフェースにmultiplyメソッドを追加しました。Beanクラスではmultiplyメソッドからaaddメソッドを呼び出すようにします。インターセプターは昨日使用したTraceInterceptorをそのまま使います。Clientはmultiplyメソッドを呼び出します。
ビジネスインタフェース

public interface Calculator {
  public int add(int x, int y);
  public int subtract(int x, int y);
  public int multiply(int x, int y);
}

Beanクラス

@Stateless
@Remote( { Calculator.class })
@Interceptors( { TraceInterceptor.class })
public class CalculatorBean implements Calculator {

  public int add(int a, int b) {
    return a + b;
  }

  public int subtract(int a, int b) {
    return a - b;
  }
  
  public int multiply(int a, int b) {
    int ret = 0;
    for (int i = 0; i < Math.abs(b); i++) {
      ret = add(ret, a);
    }
    return b > 0 ? ret : -ret;
  }

}

クライアント

public class Client {
  public static void main(String[] args) throws Exception {
    InitialContext ctx = new InitialContext();
    Calculator calc = (Calculator) ctx.lookup(Calculator.class.getName());
    System.out.println(calc.multiply(2, 5));
  }
}

標準出力JBossのコンソールには次のように出力されます。

01:14:07,957 INFO  [STDOUT] BEGIN study.ejb.CalculatorBean#multiply(2, 5)
01:14:07,957 INFO  [STDOUT] END study.ejb.CalculatorBean#multiply(2, 5) : 10 Executed Interceptor(s):1

標準出力の内容からaddメソッドを呼び出したときのインターセプタは動いてないことがわかります。ひがさんの指摘どおりでした。JBossのインターセプタはやっぱりProxyタイプということですね。javassist使ってるからってByteコード拡張タイプではないんですね(JBossがどこでjavassistを使っているのかわかってないんですが...)。

AOP Alianceの欠点やProxyタイプの問題点の話題がJ2EE勉強会の議事録にありましたです。

うーん、EJB 3.0の策定者の方たちはやProxyタイプの問題やInvocationContextでByteコード拡張形式のAOP実装をサポートしきれていないことをどう考えているんでしょう。それとちょっと気になるんですけど世の中のAOP実装ってProxyタイプが主流なんでしょうか。