JAVA AOP简单实践(基于SpringBoot)
天行健,君子以自强不息;地势坤,君子以厚德载物。
每个人都有惰性,但不断学习是好好生活的根本,共勉!
文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。
床前明月光,疑是地上霜。
举头望明月,低头思故乡。
——《静夜思》
文章目录
- JAVA AOP简单实践(基于SpringBoot)
- 1. 依赖引入
- 2. 完整依赖
- 3. 项目包结构
- 4. 项目启动类
- 5. 切面类
- 5.1 类创建
- 5.2 切点实现
- 5.3 前置通知
- 5.4 环绕通知
- 5.5 后置通知
- 5.6 返回通知
- 5.7 报错通知
- 5.8 完整切面类代码
- 6. 请求接口的实现
- 6.1 AopTestController.java
- 6.2 AopTest2Controller.java
- 6.3 AopTest3Controller.java
- 7. 测试接口
- 7.1 AopTestController.java的方法
- 7.2 AopTest2Controller.java的方法
- 7.3 AopTest3Controller.java的方法
- 8. 输出打印
- 8.1 test1输出结果
- 8.2 test2输出结果
- 8.3 test3输出结果
- 9. 总结
- 加分加分
- 1. 加分
- 2. 加分
- 3. 加分
- 4. 加分
- 4.1 加分1
- 4.2 加分2
- 4.3 加分3
- 4.4 加分4
关于aop的完整详细版可跳转到链接:Java AOP 介绍与实践
JAVA AOP简单实践(基于SpringBoot)
以下为AOP的简单实现
本项目demo以springboot框架实现
1. 依赖引入
引入aop的依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.7.18</version></dependency>
当然了,除了aop的依赖,本demo中还用到了其他依赖
2. 完整依赖
项目的所有依赖如下
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.hslb</groupId><artifactId>aop_demo</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.7.18</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.7.18</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.32</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.34</version></dependency></dependencies></project>
3. 项目包结构
该demo的包结构如下,可自行创建,主要为了测试aop匹配不同层级的包的情况
4. 项目启动类
AopApplication.java
package com.aop;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;/*** @ClassDescription: 项目启动类* 使用@EnableAspectJAutoProxy(proxyTargetClass = true)开启aop* @JdkVersion: 1.8* @Author: 李白* @Created: 2024/12/21 14:33*/
@EnableAspectJAutoProxy(proxyTargetClass = true)
@SpringBootApplication
public class AopApplication {public static void main(String[] args) {SpringApplication.run(AopApplication.class, args);}}
5. 切面类
以下切面类分多个部分进行拆分实现,最后有完整的切面类代码
5.1 类创建
创建切面类AopAspectJ.java
并在类上使用注解@Aspect标记该类为切面类,同时需要使用@Component注解将其标记为Bean
package com.aop.common;import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;/*** @ClassDescription: aop切面类* @JdkVersion: 1.8* @Author: 李白* @Created: 2024/12/21 14:35*/
@Aspect
@Component
public class AopAspectJ {}
5.2 切点实现
在AopAspectJ.java类中定义一个切点方法
方法修饰符为public
返回值为void
方法名自定义
在方法上使用@Pointcut注解将其标记为切点方法
同时在注解中将匹配条件填入,以此来进行拦截满足条件的方法
/*** 定义切入点方法,方法名自定义,无参数,无内容,定义的方法名后续注解需要使用,以此方法切入*/
// @Pointcut(value = "execution(* com.aop..*(..))")
// @Pointcut(value = "execution(* com.aop..*.*(..))")
// @Pointcut(value = "execution(* com.aop.controller.*.*(..))")@Pointcut(value = "execution(* com.aop.*.*.*(..))")public void pointcut(){}
5.3 前置通知
在AopAspectJ.java类中定义前置通知,进行方法执行前的逻辑实现
/*** 定义前置通知@Beafore*/@Before(value = "pointcut()")public void before(){System.out.println("前置通知@Before------------------>");}
5.4 环绕通知
在AopAspectJ.java类中定义环绕通知,进行方法执行前、中、后的逻辑实现
/*** 定义环绕置通知@Around* @param proceedingJoinPoint 连接点* @throws Throwable 抛错*/@Around(value = "pointcut()")public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {//前置逻辑System.out.println("环绕通知@Around 执行前------------------>");//执行被通知的方法proceedingJoinPoint.proceed();//后置逻辑System.out.println("环绕通知@Around 执行后------------------>");}
5.5 后置通知
在AopAspectJ.java类中定义后置通知,进行方法执行后的逻辑实现
/*** 定义后置通知@After*/@After(value = "pointcut()")public void after(){System.out.println("后置通知@After------------------>");}
5.6 返回通知
在AopAspectJ.java类中定义返回通知,进行方法执行后并成功返回后的逻辑实现
/*** 定义返回通知@AfterReturning* @param joinPoint 连接点* @param result 返回结果* @return 返回*/@AfterReturning(value = "pointcut()", returning = "result")public JSONObject afterReturning(JoinPoint joinPoint, JSONObject result){System.out.println("返回通知@AfterReturning------------------>");return null;}
5.7 报错通知
在AopAspectJ.java类中定义报错通知,进行方法执行失败后的逻辑实现
/*** 定义报错通知@AfterThrowing*/@AfterThrowing(value = "pointcut()")public void afterThrowing(){System.out.println("报错通知@AfterThrowing------------------>");}
5.8 完整切面类代码
以下为切面类的完整代码实现
AopAspectJ.java
package com.aop.common;import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;/*** @ClassDescription: aop切面类* @JdkVersion: 1.8* @Author: 李白* @Created: 2024/12/21 14:35*/
@Aspect
@Component
public class AopAspectJ {/*** 定义切入点方法,方法名自定义,无参数,无内容,定义的方法名后续注解需要使用,以此方法切入*/
// @Pointcut(value = "execution(* com.aop..*(..))")
// @Pointcut(value = "execution(* com.aop..*.*(..))")
// @Pointcut(value = "execution(* com.aop.controller.*.*(..))")@Pointcut(value = "execution(* com.aop.*.*.*(..))")public void pointcut(){}/*** 定义前置通知@Beafore*/@Before(value = "pointcut()")public void before(){System.out.println("前置通知@Before------------------>");}/*** 定义环绕置通知@Around* @param proceedingJoinPoint 连接点* @throws Throwable 抛错*/@Around(value = "pointcut()")public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {//前置逻辑System.out.println("环绕通知@Around 执行前------------------>");//执行被通知的方法proceedingJoinPoint.proceed();//后置逻辑System.out.println("环绕通知@Around 执行后------------------>");}/*** 定义后置通知@After*/@After(value = "pointcut()")public void after(){System.out.println("后置通知@After------------------>");}/*** 定义返回通知@AfterReturning* @param joinPoint 连接点* @param result 返回结果* @return 返回*/@AfterReturning(value = "pointcut()", returning = "result")public JSONObject afterReturning(JoinPoint joinPoint, JSONObject result){System.out.println("返回通知@AfterReturning------------------>");return null;}/*** 定义报错通知@AfterThrowing*/@AfterThrowing(value = "pointcut()")public void afterThrowing(){System.out.println("报错通知@AfterThrowing------------------>");}}
6. 请求接口的实现
在不同的包中创建请求接口,接口类中的请求路径不同且输出也不同,然后通过表达式不同的拦截条件进行测试不同的接口
查看输出内容即可验证
6.1 AopTestController.java
com.aop.controller.AopTestController.java类
package com.aop.controller;import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.*;/*** @ClassDescription: 请求测试类* @JdkVersion: 1.8* @Author: 李白* @Created: 2024/12/21 14:34*/
@RestController
@RequestMapping(value = "/aop")
public class AopTestController {@GetMapping(value = "test1")public JSONObject test1(@RequestHeader("token")String token,@RequestParam("username")String username){JSONObject jsonObject = new JSONObject();jsonObject.put("token", token);jsonObject.put("username", username);System.out.println("aop test1 token: "+token+" username: "+username);return jsonObject;}}
6.2 AopTest2Controller.java
com.aop.common.AopTest2Controller.java类
package com.aop.common;import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.*;/*** @ClassDescription: 请求测试类* @JdkVersion: 1.8* @Author: 李白* @Created: 2024/12/21 14:34*/
@RestController
@RequestMapping(value = "/aop2")
public class AopTest2Controller {@GetMapping(value = "test2")public JSONObject test1(@RequestHeader("token")String token,@RequestParam("username")String username){JSONObject jsonObject = new JSONObject();jsonObject.put("token", token);jsonObject.put("username", username);System.out.println("aop test2 token: "+token+" username: "+username);return jsonObject;}}
6.3 AopTest3Controller.java
com.aop.common.test.AopTest3Controller.java类
package com.aop.common.test;import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.*;/*** @ClassDescription: 请求测试类* @JdkVersion: 1.8* @Author: 李白* @Created: 2024/12/21 14:34*/
@RestController
@RequestMapping(value = "/aop3")
public class AopTest3Controller {@GetMapping(value = "test3")public JSONObject test1(@RequestHeader("token")String token,@RequestParam("username")String username){JSONObject jsonObject = new JSONObject();jsonObject.put("token", token);jsonObject.put("username", username);System.out.println("aop test3 token: "+token+" username: "+username);return jsonObject;}}
7. 测试接口
启动项目
使用postman进行请求接口测试
依次调用三个接口
7.1 AopTestController.java的方法
请求方式
Get
请求地址
127.0.0.1:8080/aop/test1
请求头参数
请求参数
7.2 AopTest2Controller.java的方法
请求方式
Get
请求地址
127.0.0.1:8080/aop2/test2
请求参数和值都与上一个接口一样
7.3 AopTest3Controller.java的方法
请求方式
Get
请求地址
127.0.0.1:8080/aop3/test3
请求参数和值都与上一个接口一样
8. 输出打印
在postman中分别调用三个接口
控制台输出内容依次如下
8.1 test1输出结果
AopTestController.java中test1的输出结果如下
环绕通知@Around 执行前------------------>
前置通知@Before------------------>
aop test1 token: 13579 username: libai
返回通知@AfterReturning------------------>
后置通知@After------------------>
环绕通知@Around 执行后------------------>
8.2 test2输出结果
AopTest2Controller.java中test1的输出结果如下
环绕通知@Around 执行前------------------>
前置通知@Before------------------>
aop test2 token: 13579 username: libai
返回通知@AfterReturning------------------>
后置通知@After------------------>
环绕通知@Around 执行后------------------>
8.3 test3输出结果
AopTest3Controller.java中test1的输出结果如下
aop test3 token: 13579 username: libai
9. 总结
因为我们的表达式是execution(* com.aop.*.*.*(..))
该表达式拦截的是com.aop包下一级包中的所有类的所有方法,不包含下一级包的子包
test1和test2都是aop下一级包的类中的方法
test1是aop.controller包下的类的方法
test2是aop.common包下的类的方法
而test3是aop.common.test包下类的方法,已经是aop包下一级包common包的子包test包下的方法,多了一级,因此拦截不到
感谢阅读,祝君暴富!
版权声明:
- 作者:寒山李白
- 博客地址:https://hanshan.blog.csdn.net/
- 版权:本作品采用《创作共享许可证》进行许可,根据该许可授权的内容可在符合本许可证条款的前提下自由使用、、修改和创作衍生作品。
版权许可介绍:
本文采用CC BY-NC-SA许可证
此许可允许在使用者仅出于非商业目的以任何媒体或格式分发、重新混合、改编和构建材料,并且前提是注明创作者。如果您重新混合、改编或基于该材料进行构建,则必须按照相同的条款对修改后的材料进行许可。
更多信息请访问以下网址查看:
版权官网 https://creativecommons.org/licenses/by-nc-sa/4.0/
中文翻译 https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh-hans
文章结束
--------------------------------------------------------------------------------------------------------------------------------------
以下内容增加文章评分用,可忽略
加分加分
黄河之水天上来,奔流到海不复回
高堂明镜悲白发,朝如青丝暮成雪
1. 加分
黄河之水天上来,奔流到海不复回
高堂明镜悲白发,朝如青丝暮成雪
2. 加分
黄河之水天上来,奔流到海不复回
高堂明镜悲白发,朝如青丝暮成雪
3. 加分
寒山李白
寒山李白
4. 加分
账号密码
名称 | 密码 |
---|---|
李白 | 123 |
4.1 加分1
账号密码
名称 | 密码 |
---|---|
李白 | 123 |
4.2 加分2
账号密码
名称 | 密码 |
---|---|
李白 | 123 |
4.3 加分3
账号密码
名称 | 密码 |
---|---|
李白 | 123 |
4.4 加分4
账号密码
名称 | 密码 |
---|---|
李白 | 123 |