2012-04-27 17 views
5

我有一些方法會拋出一些異常,我想用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中是行不通的。

回答

10

你能避免捕獲異常,只是使用try /終於沒有catch塊。 如果你真的需要登錄異常可以拋出建議後使用,如:

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); 
    } 

} 
+0

感謝,這是非常簡單的解決方案。 – 2012-04-28 09:43:50

6

恐怕你不能寫建議拋出未申報的匹配連接點拋出異常。每:http://www.eclipse.org/aspectj/doc/released/progguide/semantics-advice.html: 「的意見聲明必須包含一個throws子句列出檢查的異常身體可能拋出checked異常的這份清單必須與每個目標兼容加盟諮詢點,或錯誤是由編譯器發出信號。」

目前已AspectJ的郵件列表上討論了關於改善這種情況 - 會見到這樣的:http://dev.eclipse.org/mhonarc/lists/aspectj-dev/msg01412.html

但基本上你需要做的是爲例外聲明的每個變體不同的意見。例如:

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

這將告訴到處都有3個例外。

1

有一個「醜」的解決方法 - 我發現他們在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); 
    } 
}