7

いくつかの例外をスローするメソッドがいくつかあります。AspectJを使用して、実行時間を計算し、例外がスローされた場合はエラーログにログインし、例外を再スローしてフローを続行するようにアドバイスしたいと思います。

次のようにしてこれを達成しようとしましたが、eclipseに「未処理の例外タイプ」と表示されます。

コード-aspectjが使用される相手:-

public interface Iface {
    public void reload() throws TException;

    public TUser getUserFromUserId(int userId, String serverId) throws ResumeNotFoundException, TException;

    public TUser getUserFromUsername(String username, String serverId) throws  ResumeNotFoundException, TException;

    public TResume getPartialActiveProfileFromUserId(int userId, int sectionsBitField, String serverId) throws ResumeNotFoundException, UserNotFoundException;

    public TResume getPartialActiveProfileFromUsername(String username, int sectionsBitField, String serverId) throws ResumeNotFoundException, UserNotFoundException, TException;
}

コードaspectj:-

public aspect AspectServerLog {

public static final Logger ERR_LOG = LoggerFactory.getLogger("error");

Object around() : call (* com.abc.Iface.* (..)) {
    Object ret;
    Throwable ex = null;

    StopWatch watch = new Slf4JStopWatch();

    try {
    ret = proceed();
    }catch (UserNotFoundException e) {
    ex = e ;
     throw e ;
    } catch (ResumeNotFoundException e) {
    ex = e ;
    throw e ;
    } catch (Throwable e) {
    ex = e ;
    throw new RuntimeException(e);
    }finally{

    watch.stop(thisJoinPoint.toShortString());

    if(ex!=null){
        StringBuilder mesg = new StringBuilder("Exception in ");
        mesg.append(thisJoinPoint.toShortString()).append('(');
        for(Object o : thisJoinPoint.getArgs()) {
        mesg.append(o).append(',');
        }
        mesg.append(')');

        ERR_LOG.error(mesg.toString(), ex);
        numEx++;
    }

   }
return ret;
}
}

このAspectJが機能しない理由を教えてください。

4

3 に答える 3

12

例外のキャッチを回避し、キャッチなしでtry/finallyブロックを使用することができます。そして、本当に例外をログに記録する必要がある場合は、次のようなアドバイスをスローした後に使用できます。

public aspect AspectServerLog {

    public static final Logger ERR_LOG = LoggerFactory.getLogger("error");

    Object around() : call (* com.abc.Iface.* (..)) {

        StopWatch watch = new Slf4JStopWatch();

        try {
            return proceed();
        } finally {
            watch.stop(thisJoinPoint.toShortString());
        }
    }

    after() throwing (Exception ex) : call (* com.abc.Iface.* (..)) {
        StringBuilder mesg = new StringBuilder("Exception in ");
        mesg.append(thisJoinPoint.toShortString()).append('(');
        for (Object o : thisJoinPoint.getArgs()) {
            mesg.append(o).append(',');
        }
        mesg.append(')');

        ERR_LOG.error(mesg.toString(), ex);
    }

}
于 2012-04-28T00:50:38.383 に答える
6

一致したジョインポイントでスローされることが宣言されていない例外をスローするためのアドバイスを書くことはできません。Per:http ://www.eclipse.org/aspectj/doc/released/progguide/semantics-advice.html: "アドバイス宣言には、本文がスローする可能性のあるチェック済み例外をリストするthrows句を含める必要があります。このチェック済み例外のリストは、アドバイスの各ターゲット参加ポイントと互換性があるか、コンパイラーによってエラーが通知されます。」

この状況を改善することについて、aspectjメーリングリストで議論がありました-次のようなスレッドを参照してください:http://dev.eclipse.org/mhonarc/lists/aspectj-dev/msg01412.html

ただし、基本的には、例外宣言のバリアントごとに異なるアドバイスを行う必要があります。例えば:

Object around() throws ResumeServiceException, ResumeNotFoundException, TException: 
  call (* Iface.* (..) throws ResumeServiceException, ResumeNotFoundException, TException) {

それはそれらの3つの例外があるすべての場所にアドバイスします。

于 2012-04-27T17:25:23.933 に答える
3

「醜い」回避策があります-私はSpring4でそれらを見つけましたAbstractTransactionAspect

Object around(...): ... {
    try {
        return proceed(...);
    }
    catch (RuntimeException ex) {
        throw ex;
    }
    catch (Error err) {
        throw err;
    }
    catch (Throwable thr) {
        Rethrower.rethrow(thr);
        throw new IllegalStateException("Should never get here", thr);
    }
}

/**
 * Ugly but safe workaround: We need to be able to propagate checked exceptions,
 * despite AspectJ around advice supporting specifically declared exceptions only.
 */
private static class Rethrower {

    public static void rethrow(final Throwable exception) {
        class CheckedExceptionRethrower<T extends Throwable> {
            @SuppressWarnings("unchecked")
            private void rethrow(Throwable exception) throws T {
                throw (T) exception;
            }
        }
        new CheckedExceptionRethrower<RuntimeException>().rethrow(exception);
    }
}
于 2017-11-28T15:59:25.587 に答える