SpringBoot中AspectJ的使用
2021/10/15 14:14:27
本文主要是介绍SpringBoot中AspectJ的使用,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
SpringBoot中AspectJ的使用
AspectJ作为语言级别的AOP框架,功能相比于SpringAOP更加强大。SpringAOP旨在提供给用户一个轻量级的AOP实现方案,它只能应用在SpringIOC容器中管理的bean。而AspectJ旨在提供给用户一个完整的AOP解决方案,它可以应用在所有的域对象中。
- AspectJ织入代码方式
AspectJ在织入代码时,有三种不同类型的编织:
官网对于织入时机的解释
- 编译时织入(CTW)
- 编译后织入 (BTW)
- 类加载时织入 (LTW)
- SpringAOP织入代码方式
SpringAOP是基于动态代理来实现的,在运行期通过接口或者子类的方式来实现AOP。在SpringAOP中主要有两种:
- JDK动态代理(基于接口实现)
- CGLib动态代理(基于类实现)
本文主要介绍AspectJ在SpringBoot中的两种实现(CTW、LTW)
1. CTW的实现
使用CTW的方式织入时,需要采用特殊的编译器(ajc)来进行编译
- IDEA的相关配置
在Setting将Java Complier替换为Ajc编译器
注意:必须现在项目中导入aspectjtools.jar
在Project Structure中导入依赖包aspectjrt.jar
在facets中添加AspectJ
- 相关设置
aop.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd"> <aspectj> <weaver> <include within="com.zakary.qingblog..*" /> </weaver> <aspects> <aspect name="com.zakary.qingblog.aop.LoginAspect"/> <aspect name="com.zakary.qingblog.aop.InterceptorAspect"/> <aspect name="com.zakary.qingblog.aop.ParamsCheckAspect"/> </aspects> </aspectj>
- 切面实现
切面
@Aspect @DeclarePrecedence("InterceptorAspect,LoginAspect,ParamsCheckAspect") public class LoginAspect { private Logger logger= LoggerFactory.getLogger(QingblogApplication.class); /** * 匹配规则 * execution: 用于匹配方法执行的连接点; * execution(public * *(..)) ==> 匹配所有目标类的public方法,第一个*代表返回类型,第二个*代表方法名,而..代表任意入参的方法。 * execution(* com.oysept.springboot.controller..*.*(..)) ==> 该包及所有子包下任何类的任何方法。 * execution(* com.oysept.springboot.controller.*(..)) ==> 该包下任何类的任何方法。 * execution(* com.oysept.springboot.controller.AspectJController.*(..)) ==> 该包下AspectJController类的任何方法。 * execution(* com..*.*Controller.method*(..)) ==> 匹配包名前缀为com的任何包下类名后缀为Controller的方法,方法名必须以method为前缀。 * execution(* *To(..)) ==> 匹配目标类所有以To为后缀的方法。 * 注: 该方法只是为了声明一个公共的环绕通知,也可以直接在具体方法配置,如: @Around("execution(* com.oysept.springboot.controller..*.*(..))") */ @Pointcut("execution(* com.zakary.qingblog.controller.LoginController.userLogin(..))") public void loginAop() {} @Before("loginAop()") public void before(JoinPoint point) throws Throwable { Object[] objArgs = point.getArgs(); String mail= AnalysisUtils.getObjectToMap(objArgs[0]).get("userMail").toString(); String password=AnalysisUtils.getObjectToMap(objArgs[0]).get("userPassword").toString(); logger.info("User Login : [ userMail : "+mail+"\t , password : "+password+"\t ]"); } }
切入点
@Controller public class LoginController { @Autowired private LoginService loginService; @RequestMapping("/userLogin") @ResponseBody public JSONResult userLogin(@RequestBody @Validated({ValidationGroups.LoginGroup.class}) User user, HttpServletRequest request){ User user1=loginService.login(user); HttpSession session=request.getSession(); session.setAttribute("userId",user1.getUserId()); return JSONResult.ok("success"); } }
编译后的class文件
@Controller public class LoginController { @Autowired private LoginService loginService; public LoginController() { } @RequestMapping({"/userLogin"}) @ResponseBody public JSONResult userLogin(@RequestBody @Validated({LoginGroup.class}) User user, HttpServletRequest request) { JoinPoint var5 = Factory.makeJP(ajc$tjp_0, this, this, user, request); JSONResult var9; try { LoggerAspect.aspectOf().before(var5); LoginAspect.aspectOf().before(var5); ParamsCheckAspect.aspectOf().beforeLogin(var5); User user1 = this.loginService.login(user); HttpSession session = request.getSession(); session.setAttribute("userId", user1.getUserId()); var9 = JSONResult.ok("success"); } catch (Throwable var10) { LoggerAspect.aspectOf().releaseResource(var5); throw var10; } LoggerAspect.aspectOf().releaseResource(var5); return var9; } static { ajc$preClinit(); } }
图中执行了多个AspectOf方法,因为我在此处实现了多个切面
2. LTW的实现
- IDEA的相关配置
RUN->Edit Configurations->Configuration->Main Class->Environment->VM options填入
-javaagent:"C:\Users\Zakary.m2\repository\org\aspectj\aspectjweaver\1.9.5\aspectjweaver-1.9.5.jar"
-javaagent:"C:\Users\Zakary.m2\repository\org\springframework\spring-instrument\5.1.9.RELEASE\spring-instrument-5.1.9.RELEASE.jar"
此包在maven仓库中可以下载 - application.yml
spring: aop: auto: false
关闭Springaop
设置ltw CustomLtwConfig.java
@Configuration @ComponentScan("com.zakary.qingblog.controller") @EnableLoadTimeWeaving(aspectjWeaving=ENABLED) public class CustomLtwConfig{ }
注:aspectjWeaving有三个值,ENABLED为强制使用LTW的方式,DISENABLED不使用,AUTODETECT为查找META-INF下有无aop.xml文件,如果没有,不使用LTW,有的话使用LTW
- 切面实现同上
3. 多切面执行顺序的解决方案
- 如果采用SpringAop时,同一个切点含有多个advice时,使用@order注解来决定每个advice的执行顺序,其中value值越小越先执行。但@order不能使用在aspectj的切面中,@order只能决定SpringIOC容器中的bean。
- 采用AspectJ时,使用注解@DeclarePrecedence,参数为切面类,
例如
@DeclarePrecedence("InterceptorAspect,LoginAspect,ParamsCheckAspect")
参考文章
CTW
LTW
这篇关于SpringBoot中AspectJ的使用的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-09-28微服务架构中API版本控制的实践
- 2024-09-28AI给的和自己写的Python代码,都无法改变输入框的内容,替换也不行
- 2024-09-27Sentinel配置限流资料:新手入门教程
- 2024-09-27Sentinel配置限流资料详解
- 2024-09-27Sentinel限流资料:新手入门教程
- 2024-09-26Sentinel限流资料入门详解
- 2024-09-26Springboot框架资料:初学者入门教程
- 2024-09-26Springboot框架资料详解:新手入门教程
- 2024-09-26Springboot企业级开发资料:新手入门指南
- 2024-09-26SpringBoot企业级开发资料新手指南