使用AspectJ為帶註釋的類建議方法

1.概述

在本教程中,我們將在調用已配置類的方法時使用AspectJ編寫跟踪日誌記錄輸出。通過使用AOP建議來編寫跟踪日誌輸出,我們將邏輯封裝到單個編譯單元中。

我們的示例擴展了AspectJ簡介中提供的信息。

2.跟踪記錄註釋

我們將使用註解來配置類,以便可以跟踪其方法調用。使用註解為我們提供了一種簡便的機制,可以將跟踪日誌記錄輸出添加到新代碼中,而不必直接添加日誌記錄語句。

讓我們創建註解:

@Retention(RetentionPolicy.RUNTIME)

 @Target(ElementType.TYPE)

 public @interface Trace {

 }

3.創建我們的Aspect

我們將創建一個方面來定義pointcut以匹配我們關心的連接點以及包含要執行的邏輯around

我們的方面將類似於以下內容:

public aspect TracingAspect {

 private static final Log LOG = LogFactory.getLog(TracingAspect.class);



 pointcut traceAnnotatedClasses(): within(@Trace *) && execution(* *(..));



 Object around() : traceAnnotatedClasses() {

 String signature = thisJoinPoint.getSignature().toShortString();

 LOG.trace("Entering " + signature);

 try {

 return proceed();

 } finally {

 LOG.trace("Exiting " + signature);

 }

 }

 }

在我們方面,我們定義了一個pointcut命名traceAnnotatedClasses相匹配的execution方法within我們註釋類Trace註釋。**通過定義和命名pointcut,我們可以像使用類中的方法一樣重用它。**我們將使用這個命名的pointcut來配置我們的around建議。

**我們的around pointcut匹配的任何連接點執行,並返回一個Object 。**通過具有Object返回類型,我們可以考慮具有任何返回類型(甚至void建議方法。

我們檢索匹配的連接點的簽名,以創建String表示形式,以將上下文添加到我們的跟踪消息中。結果,我們的日誌輸出將具有該類的名稱和所執行的方法,這為我們提供了一些所需的上下文。

在兩次跟踪輸出調用之間,我們調用了一個名為proceed的方法。**此方法可用於around建議,以便繼續執行匹配的連接點。**由於我們無法在編譯時知道返回類型,因此返回類型將為Object在將最終跟踪輸出發送到日誌之後,我們將把該值發送回調用方。

**我們將try proceed()調用包裝在try / finally塊中,以確保寫入退出消息。**如果我們想跟踪拋出的異常,我們可以添加after()建議以在拋出異常時編寫一條日誌消息:

after() throwing (Exception e) : traceAnnotatedClasses() {

 LOG.trace("Exception thrown from " + thisJoinPoint.getSignature().toShortString(), e);

 }

4.在我們的代碼使用註解

現在我們需要啟用跟踪。讓我們創建一個簡單的類,並使用我們的自定義註釋激活跟踪日誌記錄:

@Trace

 @Component

 public class MyTracedService {



 public void performSomeLogic() {

 ...

 }



 public void performSomeAdditionalLogic() {

 ...

 }

 }

有了Trace註釋後,我們類中的方法將與我們定義pointcut執行這些方法時,跟踪消息將被寫入日誌。

運行調用這些方法的代碼後,我們的日誌輸出應包含類似於以下內容的內容:

22:37:58.867 [main] TRACE cbacTracingAspect - Entering MyTracedService.performSomeAdditionalLogic()

 22:37:58.868 [main] INFO cbacMyTracedService - Inside performSomeAdditionalLogic...

 22:37:58.868 [main] TRACE cbacTracingAspect - Exiting MyTracedService.performSomeAdditionalLogic()

 22:37:58.869 [main] TRACE cbacTracingAspect - Entering MyTracedService.performSomeLogic()

 22:37:58.869 [main] INFO cbacMyTracedService - Inside performSomeLogic...

 22:37:58.869 [main] TRACE cbacTracingAspect - Exiting MyTracedService.performSomeLogic()

5.結論

在本文中,我們使用AspectJ截獲了一個類的所有方法,並在該類上添加了一個註釋。這樣做使我們能夠快速將跟踪日誌記錄功能添加到新代碼中。

我們還將跟踪日誌輸出邏輯合併到一個編譯單元中,以提高我們隨著應用程序的發展修改跟踪日誌輸出的能力。