ThrowsInterceptor

使えないSpringのThrwosAdviceのかわりに,ひがさんが素敵なThrowsInterceptorを作ってくださいました.
SpringのThrwosAdviceがどうして使えないのかというと,問題点が二つあるのです.

  • メソッドの再実行ができない.

正確に言えばできなくはないのですが,それはjava.lang.reflect.Methodを通じて呼び出すことができるだけです.この場合,ターゲットといま例外を処理しているThrwosAdviceとの間に挟まっているAdvice(Interceptor)は実行されないはず.例えば,トランザクションAdviceがあって,その外側にデッドロックが発生した場合に限りリトライを行うAdviceを適用するなんていう場合.直接ターゲットのメソッドを実行するとトランザクションが開始されません.リトライをするには,MethodInvocationが必要ですが,ThrwosAdviceにはそれがない.なので使えません.

  • 例外を無視できない.

例外を再スローしなくても,元の例外がスローされていきます.例外を握りつぶす手段がありません.例外ハンドリングの主たる目的はその例外を捕まえて例外的な状況から正常な状況に戻すことなのに,それができない.なので使えません.


要するにSpringのThrwosAdviceは単なる傍観者にしかなれないわけです.これじゃあいまいち使えません.
それで嘆いていたSpringerに救世主,ひがさんのThrowsInterceptorは両方の問題を解消してくれる素敵なしろものです.ということで,さっそく実験してみました.ネタは「AOPその8 Throws Advice」そのままです.
まずはIgnoreExceptionAdviceThrowsInterceptorを継承するように修正します.

package study;
import org.aopalliance.intercept.MethodInvocation;

public class IgnoreExceptionAdvice extends ThrowsInterceptor {
    public void handleThrowable(Exception e, MethodInvocation methodInvocation) {
    }
}

ほとんど何も変わっていません.もともと何もしていませんからね.
これ以外の定義ファイルやAdviceを適用するFoo,実行用のMainクラスはそのまま同じものを使って実行!!

こんな仕事やってられるか!
こんな仕事やってられるか!
こんな仕事やってられるか!

素晴らしい!!!
不満をもみ消して,いやな仕事をきっちり三回やらせることができました! これがやりたかったんですよ!
なおThrowsInterceptorは,ひがさんの日記からコピペしたものにimport文を追加した以外,まったく修正していません.何も問題なしです.


いいなぁ,これ.S2とSpringで完全に同じものが使えるといいのですが,AopConfigExceptionはSpringのものですよね? これをS2で使うわけにはいかないですよねぇ.こういう例外もAOP Allianceで一通り決めてくれればいいんですけどね.無念だ.
ということで,ひがさん,バッチリです!