springboot项目中引入Aspectj并使用
環境
springboot:2.4.4
 aspectjweaver: 1.8.7
前言
今天調試接口時,遇到的aop攔截,做權限校驗,但是有個參數總是沒有傳,又因為以前這塊代碼邏輯有問題,總報null指針。所以回家后,研究了aspectj包。
這里網上有一句這樣的概括:
 spring-aop:AOP核心功能,例如代理工廠等等
aspectjweaver:簡單理解,支持切入點表達式等等
aspectjrt:簡單理解,支持aop相關注解等等
但是aspectjweaver是包含aspectjrt的,所以上面那句話,應該改為:
| spring-aop | AOP核心功能,例如代理工廠等等 | 
| aspectjweaver | 簡單理解,支持切入點表達式等等、支持aop相關注解等等 | 
引入依賴
這里假設你已經有了一個springboot的項目。
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.7</version> </dependency> <!--aspectjweaver是包含aspectjrt,所以不需要引入aspectjrt--> <!--aspectjweaver是包含aspectjrt,所以不需要引入aspectjrt--> <!--aspectjweaver是包含aspectjrt,所以不需要引入aspectjrt--> <dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.13</version> </dependency>使用
先創建一個AOP包
package com.ssm.boot.admin.user.aop;import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.SourceLocation; import org.springframework.stereotype.Component;import java.util.Arrays;@Aspect @Component public class UserAop { // @Pointcut("execution(* com.ssm.boot.admin.*(..))")@Pointcut("execution(* com.ssm.boot.admin..*(..))")public void userServiceAspect() {}@Before("userServiceAspect()")public void platformPermissionPoint(JoinPoint joinPoint) throws Throwable {//前端傳來的參數,如果攔截的方法有參數,但是前端沒有傳,則[null...]//joinPoint原本args是null,在調用getArgs()后,會從實現類中clone進行賦值Object[] args = joinPoint.getArgs();System.out.println(Arrays.toString(args));//由spring框架實現類寫死:method-executionString kind = joinPoint.getKind();System.out.println("kind--" + kind);//簽名(包括返回值)List com.ssm.boot.admin.user.controller.UserAopController.getAll(String,List)Signature signature = joinPoint.getSignature();System.out.println("signature--" + signature);//代理類的路徑:也就是全類名路徑SourceLocation sourceLocation = joinPoint.getSourceLocation();System.out.println("sourceLocation--" + sourceLocation);//代理目標方法包含全包名路徑Object target = joinPoint.getTarget();System.out.println("target--" + target);//解析切點表達式:翻譯成具體的方法,和toString()輸入結果一樣JoinPoint.StaticPart staticPart = joinPoint.getStaticPart();System.out.println("staticPart--" + staticPart);String longString = joinPoint.toLongString();//輸出完整全包路徑的execution解析的表達式System.out.println("toLongString--" + longString);//簡短輸出String shortString = joinPoint.toShortString();System.out.println("shortString--" + shortString);//和getStaticPart()一樣String s = joinPoint.toString();System.out.println("toString--" + s);} }寫個測試Controller
package com.ssm.boot.admin.user.controller;import com.ssm.boot.biz.user.UserAppService; import com.ssm.boot.model.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController public class UserAopController {@Autowired(required = false)private UserAppService userAppService;@RequestMapping("/users/get/all")public List<User> getAll(String name,@RequestParam(value = "ids", required = false)List<Integer> userIds) {return userAppService.getAll();} }執行
啟動項目,然后訪問接口:
http://localhost:8080/users/get/all 或 http://localhost:8080/users/get/all?name=yutao&ids=1,2,3上面的輸出結果:
并不是現在就可以執行了,而是我先把結果貼出來
[null, null] kind--method-execution signature--List com.ssm.boot.admin.user.controller.UserAopController.getAll(String,List) sourceLocation--org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@6d75f2f target--com.ssm.boot.admin.user.controller.UserAopController@5c00dc98 staticPart--execution(List com.ssm.boot.admin.user.controller.UserAopController.getAll(String,List)) toLongString--execution(public java.util.List com.ssm.boot.admin.user.controller.UserAopController.getAll(java.lang.String,java.util.List)) shortString--execution(UserAopController.getAll(..)) toString--execution(List com.ssm.boot.admin.user.controller.UserAopController.getAll(String,List))或
[yutao, [1, 2, 3]] ... ...遇到的問題
假設方法沒有參數,但是請求時有參數
也就是如下的情況:
@RequestMapping("/users/get/all") public List<User> getAll() {return userAppService.getAll(); }請求URL:http://localhost:8080/users/get/all?name=yutao&ids=1,2,3
那么從joinPoint.getArgs()方法中獲取的是[]
 也就是說是獲取不到name和ids這兩個參數的數據。
 必須方法上有這兩個參數,joinPoint才會幫你獲取到數據。
 joinPoint實現類是:MethodInvocationProceedingJoinPoint,這個類是spring的,它應該是利用反射確定目標方法沒有參數,也說也就不會從請求流中去獲取這兩個參數(值)。
No primary or single public constructor found for interface java.util.List - and no default construc
這個問題,因為我的controller參數這么寫的:
@RequestMapping("/users/get/all") public List<User> getAll(String name, List<Integer> userIds) {return userAppService.getAll(); }參數List<Integer>這樣是接收不了,所以需要改為:
@RequestMapping("/users/get/all") public List<User> getAll(String name,@RequestParam(value = "ids", required = false)List<Integer> userIds) {return userAppService.getAll(); }warning no match for this type name: com.xxx.xxx [Xlint:invalidAbsoluteTypeName]
原因是切面表達式錯誤
一開始:
@Pointcut("execution(* com.ssm.boot.admin.*(..))") public void userServiceAspect() { }改為:也就是多加一個.
@Pointcut("execution(* com.ssm.boot.admin..*(..))") public void userServiceAspect() { }我們要找到Spring包下子包的類進行運行,而一個.代表了運行當前包下所有的方法,.. 代表運行當前包和子包的方法
總結
今天遇到這個問題時,當時覺得即使方法里沒有這兩個參數,也說可以獲取到參數值。
 這么測試下來,看來是想多了。
參考地址:
No primary or single public constructor found for interface java.util.List - and no default construc
Spring切面編程錯誤warning no match for this type name:com.xxx.xxx [Xlint:invalidAbsoluteTypeName]
總結
以上是生活随笔為你收集整理的springboot项目中引入Aspectj并使用的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 【格蕾读C++ Primer Plus】
- 下一篇: python中查找文件当前位置的命令为t
