当前位置: 首页 > news >正文

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

http://www.lryc.cn/news/509118.html

相关文章:

  • java agent的使用【通俗易懂版】
  • 大模型学习指南
  • 单片机:实现定时器中断(数码管读秒+LED闪烁)(附带源码)
  • STM32单片机芯片与内部33 ADC 单通道连续DMA
  • 【0376】Postgres内核 分配 last safe MultiXactId
  • php时间strtotime函数引发的问题 时间判断出错
  • Kibana:LINUX_X86_64 和 DEB_X86_64两种可选下载方式的区别
  • 【LeetCode每日一题】 LeetCode 151.反转字符串中的单词
  • gitlab克隆仓库报错fatal: unable to access ‘仓库地址xxxxxxxx‘
  • 在已有vue cli项目中添加单元测试配置
  • 企业级NoSql数据库REDIS集群
  • HTML与数据抓取:GET与POST方法详解
  • 【es6复习笔记】模板字符串(3)
  • cursor保存更改操作技巧
  • ASP.NET |日常开发中定时任务详解
  • 【零基础保姆级教程】制作自己的数据集(二)——Labelme的安装与使用及常见的报错解决方法
  • Move AI技术浅析(二):输入与预处理
  • 实践KDTS-WEB从mysql迁移到kingbasev9
  • WebGIS实战开源项目:智慧机场三维可视化(学习笔记)
  • 2025年PMP项目管理考试时间一览表
  • 20241224在ubuntu20.04.6下的终端分屏软件terminator的安装以及使用
  • 打造高效租赁小程序让交易更便捷
  • 光谱相机在农业中的具体应用案例
  • Linux RTC 驱动框架
  • msyql数据库读写分离搭建
  • WWW23-多行为级联|级联图卷积网络的多行为推荐
  • 【EthIf-14】EthIfGeneral容器配置-02
  • 近实时”(NRT)搜索、倒排索引
  • Ubuntu20.04安装openMVS<成功>.colmap<成功>和openMVG<失败(已成功)>
  • 从测试服务器手动热部署到生产环境的实现