開發環境爲 IDEA,jdk1.8,Maven,SpringBoot2.1.3
AOP使用場景很多,此示例場景爲對 web 請求進行日誌記錄
一、在pom文件中導入AOP依賴
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
二、定義切面類,實現所需功能.根據需求,切面類可定義多個,且可以自定義切面類的執行順序.
/**
* 簡單的aop日誌配置
*
* @author YoonaLt
* @date 2019/10/29
*/
@Aspect // 標記此類爲切面類
@Component
@Slf4j
@Order(value = 2) // 切面類執行順序權重
public class LogAspect {
/**
* 定義切入點,可以定義多個。@After(),@Before()等只需填寫方法名"pointCut()","pointCut1()","pointCut2()"即可.
* <p>
* execution()的一些含義例如:
* execution(public * com.yoona.aop.*.*(..)),"com.yoona.aop"包下不限返回值的公共方法執行
* execution(* my*(..)),任何一個以"my"開頭的方法執行
* execution(* com.yoona.aop.AopController.*(..)),AopController接口下任意方法執行
* 在多個表達式之間使用 ||,or表示"或",使用 &&,and表示"與",!表示"非".例如:execution()||execution()
* <p>
* 還有一些其他表達式,如within(),this(),target(),args(),bean()等,與execution()使用略有差異,這裏就不一一介紹了.
* 需要注意的是,當表達式書寫錯誤時,會拋出異常:warning no match for this type name:com.xx.xx [Xlint:invalidAbsoluteTypeName]
*/
@Pointcut("execution(* com.yoona.aop.AopController.*(..))")
public void pointCut() {
}
/**
* 也可以直接定義切入點,@Before("execution(public * com.yoona.*.*(..))"),這樣就不必定義切入點 @Pointcut 了.
*
* @param joinPoint 連接點,可以獲取切入點方法的一些信息
*/
@Before("pointCut()")
public void atBefore(JoinPoint joinPoint) {
log.debug(" @Before 在方法執行前執行");
log.debug("切入點的方法名爲 " + joinPoint.getSignature().getName());
}
/**
* 方法結束後執行,無論是正常結束還是拋出異常都會執行.
*/
@After("pointCut()")
public void atAfter() {
log.debug(" @After 方法執行......");
}
/**
* 方法正常返回後執行
*
* @param o 方法返回的值
*/
@AfterReturning(pointcut = "pointCut()", returning = "o")
public void atAfterReturning(Object o) {
log.debug(" @AfterReturning 方法執行......");
log.debug("方法的返回值爲" + o.toString());
}
/**
* 方法拋出異常時執行
*
* @param t 方法拋出的異常
*/
@AfterThrowing(pointcut = "pointCut()", throwing = "t")
public void atAfterThrowing(Throwable t) {
log.debug(" @AfterThrowing 方法拋出異常時執行......");
log.debug("方法拋出的異常爲" + t.toString());
}
}
/**
* @author YoonaLt
* @date 2019/10/29
* 再定義一個執行其他功能的切面類
*/
@Aspect
@Component
@Slf4j
@Order(value = 1)
public class OtherAspect {
/**
* 其他功能切面類
*/
@Before("execution(* com.yoona.aop.AopController.*(..))")
public void atBefore() {
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
HttpServletRequest httpServletRequest = sra.getRequest();
String method = httpServletRequest.getMethod();
log.debug("其他功能切面類執行了" + "\nMethod:" + method + "\nCache-Control:" + httpServletRequest.getHeader("Cache-Control"));
}
}
三、測試接口
/**
* aop測試接口
*
* @author YoonaLt
* @date 2019/10/29
*/
@Slf4j
@RestController
@RequestMapping(value = "aop")
public class AopController {
@GetMapping(value = "test")
public Integer aopTest() {
log.debug("測試方法執行了");
// 使方法拋出異常
int i = 10 / 0;
return 10;
}
}
四、Run:
訪問接口