如果餓了就喫,困了就睡,渴了就喝,人生就太無趣了
源碼地址:https://github.com/keer123456789/springbootstudy/tree/master/aopdemo
1.依賴引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2.創建切面
創建切面類AspectLog
,該類作用是在方法前後打印日誌。代碼如下:
@Component
註解將切面類聲明爲bean,注入到spring容器中。@Aspect
註解將類聲明爲切面類@Pointcut
定義切點(用於準確定位應該在什麼地方應用切面通知),execution
用來定位切點,使用方法如圖1:可以是使用通配符*
匹配任意字符。@Before
在方法前執行@After
在方法後執行@AfterReturning
在方法執行後返回一個結果後執行@AfterThrowing
在方法執行過程中拋出異常的時候執行@Around
環繞通知,可以完成前置統通知和後置通知,使用該註解的方法的入參必須爲ProceedingJoinPoint
,ProceedingJoinPoint.process()
執行被切面的方法,可以完成前面四個註解的全部功能。可以看到配置了兩個切點,第二個爲@Around
使用,第一個被其他通知使用。
@Component
@Aspect
public class AspectLog {
protected Logger logger= LoggerFactory.getLogger(this.getClass());
@Pointcut("execution(public * com.keer.aopdemo.Controller.get1(..))")
public void aspectLog1() {
}
@Pointcut("execution(public * com.keer.aopdemo.Controller.get2(..))")
public void aspectLog2() {
}
@Before("aspectLog1()")
public void doBefore(JoinPoint joinPoint){
List<String> args=new ArrayList<>();
for(Object arg:joinPoint.getArgs()){
args.add((String) arg);
}
logger.info("AOP: 方法前執行");
logger.info("AOP: 方法名:"+joinPoint.getSignature().getName()+",方法參數:"+args.toString());
}
@After("aspectLog1()")
public void doAfter(JoinPoint joinPoint){
logger.info("AOP: 方法結束執行");
}
@AfterReturning("aspectLog1()")
public void doAfterReturn(JoinPoint joinPoint){
logger.info("AOP: 方法執行結束返回結果後執行");
}
@AfterThrowing("aspectLog1()")
public void deAfterThrowing(JoinPoint joinPoint){
logger.info("AOP: 方法拋出異常後執行");
}
@Around("aspectLog2()")
public void doAround(ProceedingJoinPoint joinPoint){
try {
List<String> args=new ArrayList<>();
for(Object arg:joinPoint.getArgs()){
args.add((String) arg);
}
logger.info("AOP: 方法前執行");
logger.info("AOP: 方法名:"+joinPoint.getSignature().getName()+",方法參數:"+args.toString());
joinPoint.proceed();
logger.info("AOP: 方法執行結束返回結果後執行");
}catch (Throwable e){
logger.info("AOP: 方法拋出異常後執行");
}
}
}
3.創建Controller進行測試
該類中創建了兩個Web請求方法,第二個使用@Around註解的切點方法,第一個方法是使用其他註解的切點方法。
@RestController
public class Controller {
protected Logger logger = LoggerFactory.getLogger(this.getClass());
@GetMapping("/get1/{name}")
public String get1(@PathVariable String name) {
logger.info("接收到請求:/get1, 數據參數:" + name);
return name + ",welcome to AOP";
}
@GetMapping("/get2/{name}")
public String get2(@PathVariable String name) {
logger.info("接收到請求:/get2, 數據參數:" + name);
return name + ",welcome to AOP";
}
}
訪問:http://127.0.0.1:8080/get1/keer,結果如圖2:
訪問:http://127.0.0.1:8080/get2/keer,結果如圖3: