之前我同事推坑 Spring Boot
框架給我,跟我說 Sping
重要觀念有兩個,一個是 注入
另一個是 AOP
。目前注入常常使用,但是不常使用 AOP,最近用點時間整理一下。
觀念
推薦
Spring AOP概念Aspect、Advice、JoinPoint、JoinCut与Execution_Anur的博客-CSDN博客_advice aspect
可以看詳細- 徹底征服 Spring AOP 之 實戰篇 - 簡書
AspectJ报错:error at ::0 can’t find referenced pointcut XXX - 楼兰胡杨 - 博客园
菜鳥工程師 肉豬: Spring AOP get method advice annotation and parameters
4.3.3 处理通知中的参数 - Spring 实战(第四版)
AOP錯誤: error at ::0 can’t find referenced pointcut XXX
1 | package com.example.demo; |
可參考:AspectJ报错:error at ::0 can’t find referenced pointcut XXX - 楼兰胡杨 - 博客园
不過我參照上面方法都失敗,所以我後來嘗試加上execution
,順利解決問題。
1 | "execution(* com.example.demo.TestClass.callMethod())") ( |
名詞小記
框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习) - 小不点啊 - 博客园
解說名詞:
- 淺談AOP以及AspectJ和Spring AOP - SegmentFault 思否
- Spring系列(四):Spring AOP详解 - toby.xu - 博客园
- 彻底征服 Spring AOP 之 理论篇 - 简书
- Spring AOP概念Aspect、Advice、JoinPoint、JoinCut与Execution_Anur的博客-CSDN博客_advice aspect
其實當初看敘述有看沒有懂,對照敘述我的理解先記錄下來,之後回頭複習希望能馬上進入狀況。
簡單我的觀點來看,Spring @Transactional
都會用代理模式,這邊AOP其實也類似做一樣動作,底層(應該)用做代理模式
去做,達成這個效果。
- JoinPoint: 中文叫
連接點
,多個執行點可執行自訂要跑的程式(Advice)。 - PointCut: 中文叫
斷點
,其中一個被選定的JoinPoint。 - Advice: 就是你當PointCut 觸發要執行的程式。
程式配置可以參考:
記錄重點
pom.xml
不知道為什麼 Spring Initializr 找不到這個,要自己加到 pom.xml
。
1 | <dependency> |
程式
src/main/java/com/example/demo/DemoApplication.java1
2
3
4
5
6
7
8
9
10
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);
var testClass = ctx.getBean(TestClass.class);
testClass.callMethod();
}
}
src/main/java/com/example/demo/TestClass.java1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
public class TestClass {
TestClass _testClass;
public void callMethod() {
System.out.println("Hello World!!!!你好世界");
_testClass.callMethod2();
}
public void callMethod2() {
System.out.println(" callMethod2");
}
}
src/main/java/com/example/demo/TestAspect.java1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class TestAspect {
"execution(* callMethod())") (
public void before(){
System.out.println("我在你前面做");
}
"execution(* callMethod())") (
public void after(){
System.out.println("我在你後面做");
}
"execution(* com.example.demo.TestClass.callMethod())") (
public Object doAroundAccessCheck(ProceedingJoinPoint pjp) throws Throwable {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 开始
Object retVal = pjp.proceed();
stopWatch.stop();
// 结束
System.out.println("invoke method: " + pjp.getSignature().getName() + ", elapsed time: " + stopWatch.getTotalTimeMillis());
return retVal;
}
}
其他重點
參考:Spring AOP中JoinPoint的用法 - 简书
Object[] getArgs(); 獲取傳入目標方法的引數物件
Object getTarget(); 獲取被代理的物件
Object getThis(); 獲取代理物件
參考:Spring AOP概念Aspect、Advice、JoinPoint、JoinCut與Execution_Anur的博客-CSDN博客_advice aspect
參考:4.3.3 处理通知中的参数 - Spring 实战(第四版)
感想
這邊源碼我有丟到 Github: malagege/spring-boot-aop-example: 範例測試
我以為很難,其實寫出範例又好像很簡單。後來想到滿多機制能用這個寫,像重試API測試,我們也可以透過AOP方式,後來我很好奇有沒有別人現成寫好的工具,發現spring-retry
可以做到這些事情。
文章整理:
- spring-retry 重試機制
- Spring Boot中使用Spring-Retry重试框架_c.的博客-CSDN博客_springboot 重试框架
- Spring 指南(spring-retry) - SegmentFault 思否
彩蛋
依賴注入循環問題。
1 | spring.main.allow-circular-references=true |