在 Spring Boot 使用 AOP 印日誌

使用 AOP (Aspect Oriented Programming) 的方式印出日誌,會比在各處程式中寫印日誌來的簡潔,集中管理印日誌的程式,避免影響閱讀業務邏輯。

建置 Log4j2

參考這篇建置 Log4j2 文章。

加入 Dependency

build.gradle 加入 Spring Boot AOP dependencies:spring-boot-starter-aop

1
2
3
4
5
6
7
8
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-aop'
compileOnly 'org.projectlombok:lombok:1.18.18'
annotationProcessor 'org.projectlombok:lombok:1.18.18'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

定義 TimeLogAspect

想像各個業務邏輯是縱向的流程,而 AOP 就是將流程橫剖後織入程式,藉此達到關注點分離。

元件上標註 @Aspect,即可定義為一個切面,注意也要將物件加註 @Component,Spring Boot 框架才得以管理這個元件。在方法上標註 @Around 指的是在切面的前、後織入程式,參數 ProceedingJoinPoint 是相對於橫切面的縱向資料流,可以由此參數取得資料流中的方法簽章和傳入參數等資訊。而 @Pointcut 定義切面的切點,例如,切點可以是有標註自定義的 Annotation,或是某個 Controller Package 下的所有 method。

以下是定義在所有標註 @TimeLog 或 Controller 的 Aspect 範例,計算執行這些方法需要多少時間,並將執行時間於方法回傳後印到日誌中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Log4j2
@Aspect
@Component
public class TimeLogAspect {

@Around("logTime() || controller()")
public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
long startMillis = System.currentTimeMillis();
Object proceed = pjp.proceed();
long executionTime = System.currentTimeMillis() - startMillis;
log.info(String.format("Completed %s in %d ms", pjp.getSignature().toShortString(), executionTime));
return proceed;
}

@Pointcut("@annotation(cc.secondbrain.demo.annotation.TimeLog)")
public void logTime() {
}

@Pointcut("execution(* cc.secondbrain.demo.controller.*.*(..))")
public void controller() {
}

}

自定義 Annotation @TimeLog 如下,

1
2
3
4
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeLog {
}

使用自定義 Annotation @TimeLog,可以自由地在想要記錄執行時間的方法上註記,但只限於 public 方法。
值得特別注意的是,假如在 Controller 註記 @TimeLog,只會印出一行執行時間的日誌,不會重複印成兩行。

1
2
3
4
5
6
7
8
9
10
@RestController
public class HelloController {

@TimeLog
@RequestMapping("/")
public String hello() {
return "Hello Spring Boot";
}

}

相關文章

使用 Go Workspaces 管理系統服務:從單體架構到分散式架構的彈性實現
技術

2024/09/15

建置 Log4j2
技術

2021/06/26