-
AOP及自定義注解使用
-
Aop即為切面編程,通常以下幾個場景回使用到:
事務
攔截
日志
等等
廢話不多說既然是Spring boot 那我們當然是使用Spring aop
使用方法
- 先介紹一下AOP的常用注解
| 注解 | 解釋 |
|---|---|
| @Pointcut | 通常使用為@Pointcut("execution(* XXXXX.*.*(..))")可以匹配連接點,及定位要切入的地方在哪里。 |
| @Before | 增強處理,表示在切入點執(zhí)行前需要進行的操作或者需要執(zhí)行的方法 |
| @After | 表示在切入點執(zhí)行后,進行哪些操作 |
| @AfterReturning | pointcut/value:用于指定該切入點對應的切入表達式,returning:該屬性值指定一個形參名,用于表示Advuce方法中可以定義與此同名的形參,該形參可用于訪問目標方法的返回值 |
| @AfterThrowing | 同上,throwing,返回異常 |
| @Around | 增強相當于以上幾種總和,很強大但最好線程安全使用 |
| @DeclareParents | value:指向你要增強功能的目標對象,這里要增強UserServiceImpl對象,defaultImpl:引入增強功能的類,這里配置為UserValidatorImpl,用來提供校驗用戶是否為空的功能 |
開始實際使用
- 注入pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
- 先寫切面類
@Component
@Aspect
public class Aoptest {
@Pointcut("execution(* com.example.zj.contorller.*.*(..))")
public void pc1(){}
@Before(value = "pc1()")
public void before(JoinPoint jp){
String name = jp.getSignature().getName();
System.out.println(name+"方法開始執(zhí)行");
}
@After(value = "pc1()")
public void after(JoinPoint jp){
String name = jp.getSignature().getName();
System.out.println(name+"方法執(zhí)行結束");
}
@AfterReturning(value = "pc1()",returning = "result")
public void afterReturning(JoinPoint jp,Object result){
String name = jp.getSignature().getName();
System.out.println(name+"方法返回值為"+result);
}
@AfterThrowing(value = "pc1()",throwing = "e")
public void afterThrowing(JoinPoint jp,Exception e){
String name = jp.getSignature().getName();
System.out.println(name+"方法拋出異常"+e.getMessage());
}
@Around("pc1()")
public Object around(ProceedingJoinPoint pjp)throws Throwable{
System.out.println("方法環(huán)繞先");
try {
Object o = pjp.proceed();
System.out.println("方法環(huán)繞后,結果是 :" + o);
return o;
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
}
- controller類
@RestController
public class test {
@GetMapping("test1")
public JsonResult test1(){
return new JsonResult(200,"sucess","111");
}
@GetMapping("test2")
public JsonResult test2(String name){
if(name.length() < 3 || name.length() > 10)
{
throw new IllegalArgumentException("name參數(shù)的長度必須大于3,小于10!");
}
return new JsonResult(200,"sucess","222");
}
}
- 運行項目,請求controller中定義的url,結果為:
方法環(huán)繞先
test1方法開始執(zhí)行
方法環(huán)繞后,結果是 :JsonResult(code=200, msg=sucess, result=111)
test1方法執(zhí)行結束
test1方法返回值為JsonResult(code=200, msg=sucess, result=111)
可以自行請求controller中定義的test2并拋出異常,觀察兩者執(zhí)行順序變化
-
最后講一下代碼中的
execution(* com.example.zj.contorller..*.*(..)):第一個*表示返回類型,*即為所有類型
隨后跟著包名..及表示當前包及所有子包
之后的*表示類名,*即所有類
在之后的*即為方法
(..)表示方法參數(shù)..及表示任何參數(shù)