SpringBoot 集成Spring AOP

第一步:創建SpringBoot項目,導入Maven依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
</dependency>

第二步:創建一個Aspect切面類並在其中定義好切點

@Aspect
@Component
public class WebControllerAop {
    //匹配com.hc.controller包及其子包下的所有類的所有方法
    @Pointcut("execution(public * com.hc.controller..*.*(..))")
    public void executeService()
    {
    }
}

第三步:創建一個Controller請求處理類

@RestController
@RequestMapping("/aop")
public class WebController {
}

第四步:具體測試

前置通知:方法執行之前被調用

配置前置通知:

@Before("executeService()")
 public void doBeforeAdvice(JoinPoint joinPoint) throws JsonProcessingException {
    System.out.println("前置通知!!!");
    Signature signature = joinPoint.getSignature(); //通知的簽名
    System.out.println(signature.getName()); //代理的是哪一個方法
    //獲取RequestAttributes
    RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
    //從獲取RequestAttributes中獲取HttpServletRequest的信息
    HttpServletRequest request = (HttpServletRequest) 
	requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
    Object[] obj = joinPoint.getArgs();//獲取目標方法的參數信息
    System.out.println(Arrays.toString(obj));
    if(obj.length > 0) {
        Enumeration<String> enumeration = request.getParameterNames();
        Map<String,String> parameterMap =  new HashMap();
        while (enumeration.hasMoreElements()){
            String parameter = enumeration.nextElement();
            parameterMap.put(parameter,request.getParameter(parameter));
        }
        ObjectMapper om  = new ObjectMapper();
        String str =  om.writeValueAsString(parameterMap);
        System.out.println("請求的參數信息爲:"+str);
    }
}

在Controller類裏添加一個請求處理方法來測試前面的前置通知,具體代碼如下:

@RequestMapping("/fun1")
public String fun1(@RequestParam Integer deptno, @RequestParam String dname, @RequestParam String loc) {
    System.out.println(deptno + " " + dname + " " + loc);
    return deptno + " " + dname + " " + loc;
}

啓動項目,然後在瀏覽器中請求http://localhost/aop/fun1?deptno=10&dname=sales&loc=boston時,結果如下圖所示:
在這裏插入圖片描述

後置返回通知:在方法正常返回結果之後執行

配置後置返回通知:

@AfterReturning(value = "execution(public * com.hc.controller..*.*(..))",returning = "keys")
public void doAfterReturningAdvice1(JoinPoint joinPoint,Object keys){
    System.out.println("後置返回通知的返回值:"+keys);
}

@AfterReturning(value = "execution(public * com.hc.controller..*.*(..))",returning = "keys",argNames = "keys")
public void doAfterReturningAdvice2(String keys){
    System.out.println("後置返回通知的返回值:"+keys);
}

在Controller類裏添加請求處理方法來測試前面的後置返回通知:

@RequestMapping("/fun21")
public String fun21(String key){
    return "key=: "+key;
}
@RequestMapping("/fun22")
public Integer fun22(Integer key){
    return key;
}

啓動項目,然後在瀏覽器中請求http://localhost/aop/fun21?key=asdf 時,結果如下圖所示;請求時,結果如下圖所示:
在這裏插入圖片描述
在這裏插入圖片描述

後置異常通知:在方法拋出異常之後執行

配置後置異常通知:

@AfterThrowing(value = "executeService()",throwing = "exception")
public void doAfterThrowingAdvice(JoinPoint joinPoint,Throwable exception){
    System.out.println("目標方法名:"+joinPoint.getSignature().getName());
    if(exception instanceof NullPointerException){
        System.out.println("發生了空指針異常!!!!!");
    }
}

在Controller類裏添加請求處理方法來測試前面的後置返回通知,具體代碼如下:

@RequestMapping("/fun3")
public String fun3(String key){
    throw new NullPointerException();
}

啓動項目,然後在瀏覽器中請求http://localhost/aop/fun3?key=asdf 時,結果如下圖所示:
在這裏插入圖片描述

後置最終通知:在方法執行之後執行

配置後置最終通知:

@After("executeService()")
public void doAfterAdvice(JoinPoint joinPoint){
    System.out.println("後置通知執行了!!!!");
}

在Controller類裏添加請求處理方法來測試前面的後置返回通知,具體代碼如下:

@RequestMapping("/fun41")
public String fun41(String key){
    throw new NullPointerException();
}
@RequestMapping("/fun42")
public String fun42(String key){
    return key;
}

啓動項目,然後在瀏覽器中請求http://localhost/aop/fun41?key=asdf 時,結果如下圖所示;請求http://localhost/aop/fun44?key=asdf 是,結果如下圖所示:
在這裏插入圖片描述
在這裏插入圖片描述

環繞通知:圍繞着方法執行

配置環繞通知:

@Around("execution(public * com.hc.controller..*.fun*(..))")
public Object doAroundAdvice(ProceedingJoinPoint pjp){
    Object res = null;
    System.out.println("目標方法的名稱:"+pjp.getSignature().getName());
    System.out.println("目標方法的參數:"+Arrays.toString(pjp.getArgs()));
    try {
        System.out.println("環繞通知--前置");
        res = pjp.proceed();//調用目標方法
        System.out.println("環繞通知--返回值:" + res);
    } catch (Throwable throwable) {
        System.out.println("環繞通知--異常");
        throw new RuntimeException(throwable);
    }
    System.out.println("環繞通知--後置");
    return res;
}

在Controller類裏添加請求處理方法來測試前面的後置返回通知,具體代碼如下:

@RequestMapping("/fun5")
public int fun5(int num1, int num2) {
    return num1 + num2;
}

啓動項目,然後在瀏覽器中請求http://localhost/aop/fun5?num1=123&num2=321時,結果如下圖所示:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章