使用AspectJ為帶註釋的類建議方法
- AspectJ
- AOP
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截獲了一個類的所有方法,並在該類上添加了一個註釋。這樣做使我們能夠快速將跟踪日誌記錄功能添加到新代碼中。
我們還將跟踪日誌輸出邏輯合併到一個編譯單元中,以提高我們隨著應用程序的發展修改跟踪日誌輸出的能力。