-S15: ガス欠でJAFを呼ぶ

Joinpointを呼び出す(Joinpoint#proceed())前後の時期、BeforeおよびAfterと二分して説明してきたAdviceですが、Seasar2ではもうひとつAdviceの種類を実現できます。それはJoinpointにて例外が生成した場合に動作する「Exception」 Adviceです。

list15-1. 燃料が常に切れているFuelEmptyCar.java
package tutorial.org.seasar.console;
public class FuelEmptyCar implements Car {
  public void run() {
    throw new RuntimeException("Fuel is empty.");
  }
}

list15-1は常にrun()メソッドでRuntimeExceptionを発生させます。

list15-2. 例外処理を行うJAF.java
package tutorial.org.seasar.console;
import org.seasar.framework.aop.AroundAdvice;
import org.seasar.framework.aop.Joinpoint;
public class JAF implements AroundAdvice {
  public Object invoke(Joinpoint joinpoint) throws Throwable {
    Object obj = null;
    try {
      obj = joinpoint.proceed();
    } catch(Exception e) {
      System.out.println(e.getMessage());
      System.out.println("No problem, there is a lot of fuel.");
    }
    return obj;
  }
}

list15-2では、joinpoint.proceed()をtry-catchブロックで保護しています。

public Object proceed() throws Throwable;

というメソッド定義ですから例外処理の必要が無いために、これまでは例外処理をしてきませんでしたが、ここではcatchブロックに処理を記述しています。

list15-3. JAFが助けに来るcar.xml修正版
<?xml version="1.0" encoding="UTF-8"?>
<components>
  <component class="tutorial.org.seasar.console.FuelEmptyCar">
    <aspect pointcut="run">
      <component class="tutorial.org.seasar.console.JAF"/>
    </aspect>
  </component>
</components>

設定XMLに特別なことはありません。実行結果は、

Fuel is empty.
No problem, there is a lot of fuel.

アプリケーション内で例外処理を画一的に行いたい場合に有効な技術です。Core Concernたるコンポーネントメソッドでは例外処理は行わずに、Crosscutting ConcernであるAdviceで例外処理を行うというのは、設計的にもアリなんじゃないかと個人的には思います。このへん賛否分かれると思います。