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

Springboot AOP开发

Springboot AOP开发

一 AOP概述

AOP,即面向切面编程,简言之,面向方法编程。

针对方法,在方法的执行前或执行后使用,用于增强方法,或拓展。

二 AOP开发

1.引入 spring-boot-starter-aop

在SpringBoot项目的pom文件中,引入 spring-boot-starter-aop依赖。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.示例:计算方法执行时间

1.创建实体类,通过注解来申明该类的类型,并将该类交给Spring的IOC容器来管理。

通过注解 @Aspect 申明这是一个AOP类

通过 @Component 将其交给IOC容器管理

@Aspect
@Component
public class TimeAspect {//code
}

2.创建方法并且实现

@Aspect
@Component
@Slf4j
public class TimeAspect {// 针对 com.shawn.springboot03.service 包下所有的方法进行编程,// * com.shawn.springboot03.service.*.*(..)) 为切入点表达式@Around("execution(* com.shawn.springboot03.service.*.*(..))")public Object recordTime(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {long startTime=System.currentTimeMillis();// 切面对象,执行具体的业务方法Object object = proceedingJoinPoint.proceed();long endTime=System.currentTimeMillis();log.info("方法耗时为{}ms",endTime-startTime);return object;}
}

通过以上方法,当用户调用 service 层接口的任一方法时都会计算方法的运行时间。

3.AOP编程的优点:

  • 代码无侵入:无需修改原始方法
  • 减少代码重复,提高开发效率:只需编写一次
  • 维护方便:根据业务需求,调整切入点表达式即可

三 AOP详解

1.AOP核心概念

1.连接点(JoinPoint):连接点指的是可以被AOP控制的方法,以及方法执行时的相关信息。

2.通知(Advice):Advice指的是被抽取出来的共性功能,即重复的那部分逻辑。

3.切入点(PointCut):匹配连接点的条件,通知仅会在切入点方法执行时被应用

4.切面(Aspcet):描述通知与切入点的关系

5.目标对象(Target):通知所应用的对象

2.AOP通知类型

  • @Around:环绕通知,此注解标注的方法在目标方法前后都会执行
  • @Before:前置通知,此注解标注的方法仅在方法执行前被执行
  • @After:后置通知,此注解在方法执行完成后执行,不论是否抛出异常
  • @AfterReturning:返回后通知,此注解标注的方法在目标方法后被执行,有异常不通知
  • @AfterThrowing:异常后通知,此注解的通知方法发生异常后执行

3.各通知类型演示

创建一个 TestAspect 类,用于演示各种通知类型

  1. @Around 通知类型

    介绍:在方法前后均执行

    切入点表达式格式: 返回值 包名.方法名(形参)

    其中 * 代表全部,.. 代表任意多的参数

    切入点表达式示例说明:

    * com.shawn.test.server.*(..) 表示 任意返回值的 com.shawn.test.server包下任意返回值,任意多参数的全部方法。

    @Aspect
    @Component
    @Slf4j
    public class TestAspect {@Around("execution(* com.shawn.springboot03.service.impl.DeptServiceImpl.*(..))")public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {//方法执行前的业务逻辑//code..//执行原始方法(即连接点),并且接收原始方法的返回值Object proceed = proceedingJoinPoint.proceed();//方法执行后的业务逻辑//code..//返回原始方法的返回值return proceed;}
    }
    

    ProceedingJoinPoint是一个接口类,指代程序执行过程中的一个特定点,其中包含了原始方法的全部内容,包括方法名,参数值等。

    在使用 @Around通知类型时,需要将该对象作为参数传递进来,用于后续执行原始方法或获取原始方法的其他信息。

    ProceedingJoinPoint仅能作用于 @Around 类型的通知上。

2.@Before 通知类型

介绍:此注解标注的方法仅在原始方法执行前执行

@Aspect
@Component
@Slf4j
public class TestAspect {@Before("execution(* com.shawn.springboot03.service.*.*(..))")public void before(){// 方法执行前的业务逻辑//code..}
}

3.@After 通知类型

介绍:此注解标注的方法,仅在原始方法执行后执行,且不论原始方法是否执行,该通知都会执行

@Aspect
@Component
@Slf4j
public class TestAspect {@After("execution(* com.shawn.springboot03.service.*.*(..))")public void after(){// 方法执行后的业务逻辑//code..}
}

4.@AfterReturning 通知类型

介绍:此注解标注的方法,仅在原始方法执行完成后通知,即当原始方法执行发生异常时,@AfterReturning 通知不会被执行。

@Aspect
@Component
@Slf4j
public class TestAspect {@AfterReturning("execution(* com.shawn.springboot03.service.*.*(..))")public void afterReturning(){//方法执行完成的业务逻辑//code..}
}

5.@AfterThrowing通知类型

介绍:次注解标注的方法,仅在原始方法执行过程中发生了异常,才会执行。

@Aspect
@Component
@Slf4j
public class TestAspect {@AfterThrowing("execution(* com.shawn.springboot03.service.*.*(..))")public void afterThrowing(){//方法执行时抛出异常的业务逻辑//code..}
}

4.定义切入点

以上示例中的切入点表达式均相似,可以利用封装的思想,将切入点表达式全部抽取出来,在需要的时候直接使用即可。

想要实现以上需求,则需要自定义切入点表达式

通过 @Pointcut 注解,来定义切入点表达式,然后在需要编写切入点表达式的地方调用即可。

@Aspect
@Component
@Slf4j
public class TestAspect {/*** 声明一个空的方法体来定义切入点表达式* 使用 @Pointcut 注解来定义切入点表达式*/@Pointcut("execution(* com.shawn.springboot03.service.impl.DeptServiceImpl.*(..))")private void point(){};@After("point()")public void after(){// 方法执行后的业务逻辑//code..}
}

注意:如果自定义的切入点访问修饰符为 public ,则该表达式还可以在其他切面类中被引用。具体使用可根据实际业务情况决定。

定义切入点总共有两种办法,一种是通过方法名来定义切入点,还可以通过注解来定义切入点。

示例:以下示例使用自定义注解作为切入点,使用了以下自定义注解的方法会执行通知。

@Aspect
@Component
public class TestAspect {@Pointcut("@annotation(com.shawn.springboot03.annotation.OperationLog)")private void point(){};@AfterThrowing("point()")public void afterThrowing(){//方法执行时抛出异常的业务逻辑//code..}
}

5.通知顺序

当有多个切入点都匹配到了目标方法,目标方法运行时,多个通知都会被执行。

某些情况下则需要控制通知的顺序,可以在切面类上使用 @Order 注解来控制顺序

@Aspect
@Component
@Slf4j
@Order(3)
public class TestAspect {@Pointcut("execution(* com.shawn.springboot03.service.impl.DeptServiceImpl.*(..))")private void point(){};@After("point()")public void after(){// 方法执行后的业务逻辑//code..}
}

注意:@Order(number) 注解中,数字越小的越先运行,越大的越后运行。

默认情况下,按照切面类的类名排序顺序执行。

四 切入点表达式

1.execution

execution 主要根据方法的返回值,包名类名,方法名,方法参数等信息来匹配,语法为:

execution( 访问修饰符? 返回值 包名.类名.?方法名(方法参数) throw 异常? )

其中带 ? 的表示可以省略的部分

  • 访问修饰符:可省略(比如:public,protected)
  • 包名.类名:可省略
  • throws 异常:可省略(注意是方法上声明抛出的异常,不是实际抛出的异常)

以下是一个完整示例:

@Before ("execution(public void com.itheima.service.impl.DeptserviceImpl.delete (java.lang.Integer)) throws Exception")
private void point(){};

省略后的示例:

@Before ("execution(void delete (java.lang.Integer))")
private void point(){};

此时,所有 void delete (java.lang.Integer) 方法都将被匹配到。

注意: * 用于描述匹配单个, … 可以用来匹配多个连续,?表示可省略
在这里插入图片描述

2.@annotation

@annotation 切入点表达式,用于匹配标识有特定注解的方法。

示例:

@Pointcut("@annotation(com.shawn.annotation.OperationLog)")
private void point(){};

五 连接点

在Spring中使用JoinPoint抽象了连接点,使用它可以获取方法执行时的相关信息,入目标类名,方法名,方法参数等。

1.对于 @Around 通知,获取连接点信息只能使用 ProceedingJoinPoint

@Around("point()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {//获取目标类名String name = proceedingJoinPoint.getTarget().getClass().getName();log.info("获取目标类名:"+name);//获取方法执行参数Object[] args = proceedingJoinPoint.getArgs();log.info("获取方法执行参数:"+JSON.toJSONString(args));//获取目标方法名String methodName = proceedingJoinPoint.getSignature().getName();log.info("获取目标方法名:"+methodName);//执行原始方法(即连接点),并且接收原始方法的返回值Object proceed = proceedingJoinPoint.proceed();//获取方法的返回值log.info("获取方法的返回值:"+JSON.toJSONString(proceed));//返回原始方法的返回值return proceed;
}

proceedingJoinPoint.proceed()得到目标方法的结果再返回,此处可以对目标方法执行的结果进行篡改。

2.对于其他四种通知,获取连接点信息只能使用 JoinPoint , 它是 ProceedingJoinPoint 的父类。

@Before("point()")
public void before(JoinPoint joinPoint){// 获取目标方法的类名String name = joinPoint.getTarget().getClass().getName();log.info("获取目标方法的类名:"+name);String methodName = joinPoint.getSignature().getName();log.info("获取目标方法的方法名:"+methodName);//获取目标方法的运行参数Object[] args = joinPoint.getArgs();log.info("获取目标方法的参数:"+JSON.toJSONString(args));
}

3.除@Around 通知外,还可以获取到方法执行结果的通知类型为 @AfterReturning,@AfterReturning 在方法执行完成并且无异常时通知。

在定义@AfterReturning通知类型时,使用 pointcut 属性定义切入点,returning属性定义返回值对象,然后在方法参数中传入即可。

@AfterReturning(pointcut = "point()",returning = "object")
public void afterReturning(JoinPoint joinPoint, Object object){// 获取目标方法的类名String name = joinPoint.getTarget().getClass().getName();log.info("获取目标方法的类名:"+name);String methodName = joinPoint.getSignature().getName();log.info("获取目标方法的方法名:"+methodName);//获取目标方法的运行参数Object[] args = joinPoint.getArgs();log.info("获取目标方法的参数:"+JSON.toJSONString(args));//获取方法返回值log.info("获取方法返回值:"+JSON.toJSONString(object));
}

相关文章:

Springboot AOP开发

Springboot AOP开发 一 AOP概述 AOP&#xff0c;即面向切面编程&#xff0c;简言之&#xff0c;面向方法编程。 针对方法&#xff0c;在方法的执行前或执行后使用&#xff0c;用于增强方法&#xff0c;或拓展。 二 AOP开发 1.引入 spring-boot-starter-aop 在SpringBoot项…...

office的excel中使用,告诉我详细的解决方案,如何变成转化为金额格式

在Office的Excel中&#xff0c;如果你想将名为"MEREFIELD"的公式结果转换为金额格式&#xff0c;你可以遵循以下详细步骤来实现&#xff1a; 书写MEREFIELD公式&#xff1a; 首先&#xff0c;在Excel中输入或确认你的MEREFIELD公式。例如&#xff0c;假设这个公式是用…...

灾后重建中GIS技术的关键作用与案例分析

地质灾害是指全球地壳自然地质演化过程中&#xff0c;由于地球内动力、外动力或者人为地质动力作用下导致的自然地质和人类的自然灾害突发事件。由于降水、地震等自然作用下&#xff0c;地质灾害在世界范围内频繁发生。我国除滑坡灾害外&#xff0c;还包括崩塌、泥石流、地面沉…...

java环境安装

java环境安装 一、官网下载&#xff1a; jdk&#xff0c;下载jdk&#xff0c;解压到D:\JAVA\Java\jdk目录下。 二、配置&#xff1a; 配置环境变量 鼠标右键我的电脑->属性->高级系统设置->环境变量->系统变量新建变量名JAVA_HOME&#xff0c;变量值为刚才解压的…...

如何在iStoreOS软路由系统中安装cpolar实现公网远程本地电脑桌面

文章目录 简介一、配置远程桌面公网地址二、家中使用永久固定地址 访问公司电脑**具体操作方法是&#xff1a;** 简介 软路由是PC的硬件加上路由系统来实现路由器的功能&#xff0c;也可以说是使用软件达成路由功能的路由器。 使用软路由控制局域网内计算机的好处&#xff1a…...

appium实现自动化测试原理

目录 1、Appium原理 1.1、Android Appium原理图文解析 1.1.2、原理详解 1.1.2.1、脚本端 1.1.2.2、appium-server 1.1.2.3、中间件bootstrap.jar 1.1.2.4、驱动引擎uiautomator 1.2、 IOS Appium原理 1、Appium原理 1.1、Android Appium原理图文解析 执行测试脚本全过…...

Linux:docker搭建redis集群(3主3从扩容缩容 哈希槽分配)

操作系统&#xff1a;centos7 docker-ce版本&#xff1a;24.0.7 1.准备redis镜像 我这里使用redis 6.0.8 镜像进行操作&#xff0c;如果你也需要镜像&#xff0c;在网络正常情况下直接使用 docker pull redis:6.0.8 即可进行下载&#xff0c;如果你没配置国内加速器&#x…...

Linux程序性能分析60秒+

Linux性能分析大师Brendan Gregg有一篇非常著名的博客&#xff0c;介绍在性能分析开始的60秒内&#xff0c;利用标准的Linux命令行工具&#xff0c;执行一次充分的性能检查&#xff0c;获得系统资源利用率和进程运行情况的整体概念&#xff0c;查看是否存在异常、评估饱和度。本…...

mmap映射文件使用示例

mmap 零拷贝技术可以应用于很多场景&#xff0c;其中一个典型的应用场景是网络文件传输。 假设我们需要将一个大文件传输到远程服务器上。在传统的方式下&#xff0c;我们可能需要将文件内容读入内存&#xff0c;然后再将数据从内存复制到网络协议栈中&#xff0c;最终发送到远…...

Linux命令:stat命令

目录 1 简介2 说明3 实例-L&#xff1a;显示链接指向的文件的信息-f&#xff1a;显示文件系统信息-t&#xff1a;以简洁的形式输出 1 简介 stat命令&#xff1a;显示文件或文件系统的状态 2 说明 使用&#xff1a;stat [OPTION]… FILE 常用选项&#xff1a; -L, --derefer…...

学会自幂数

学会自幂数 题目描述&#xff1a; 写⼀个代码打印1~100000之间的所有的自幂数&#xff0c;中间用空格分隔。 解法思路&#xff1a; 自幂数是又称自客单位数&#xff0c;是指一个整数各个位的立方和等于该整数本身的数。例如&#xff0c;153是自幂数&#xff0c;因为 1^35 ^…...

支付宝支付

文章目录 支付宝介绍接入条件支付宝开发支付流程关于回调 支付测试第三方库的sdk接口加密的两种方式第三方支付宝sdk支付宝支付封装 支付宝介绍 -https://open.alipay.com/develop/manage 扫码登录 -网站支付&#xff1a;https://opendocs.alipay.com/open/270/105899 扫码登录…...

qt中读写锁与互斥锁的区别

在Qt中&#xff0c;读写锁&#xff08;QReadWriteLock&#xff09;和互斥锁&#xff08;QMutex&#xff09;都是用于多线程编程时控制共享资源访问的工具&#xff0c;但它们在实现上有一些重要的区别。 QMutex&#xff08;互斥锁&#xff09;&#xff1a; QMutex是最基本的锁…...

Why Not Http?

游戏服务器开发主要是基于socket&#xff0c;或者websocket&#xff0c;很少采用http&#xff08;可能有部分非常轻量级的服务器选择http&#xff09;。这是什么原因呢&#xff1f;我们先来看看socket与http之间的区别。 socket与http之间的区别 socket与http对比 sockethttpT…...

基于JAVA的停车场收费系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 停车位模块2.2 车辆模块2.3 停车收费模块2.4 IC卡模块2.5 IC卡挂失模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 停车场表3.2.2 车辆表3.2.3 停车收费表3.2.4 IC 卡表3.2.5 IC 卡挂失表 四、系统实现五、核心代码…...

在PyTorch中,如何查看深度学习模型的每一层结构?

这里写目录标题 1. 使用print(model)2. 使用torchsummary库3.其余方法&#xff08;可以参考&#xff09; 在PyTorch中&#xff0c;如果想查看深度学习模型的每一层结构&#xff0c;可以使用print(model)或者model.summary()&#xff08;如果你使用的是torchsummary库&#xff0…...

洛谷-P1478-陶陶摘苹果(升级版)(贪心)

陶陶摘苹果&#xff08;升级版&#xff09; 题目描述 又是一年秋季时&#xff0c;陶陶家的苹果树结了 n n n 个果子。陶陶又跑去摘苹果&#xff0c;这次他有一个 a a a 公分的椅子。当他手够不着时&#xff0c;他会站到椅子上再试试。 这次与 NOIp2005 普及组第一题不同的…...

【大数据面试题】007 谈一谈 Flink 背压

一步一个脚印&#xff0c;一天一道面试题&#xff08;有些难点的面试题不一定每天都能发&#xff0c;但每天都会写&#xff09; 什么是背压 Backpressure 在流式处理框架中&#xff0c;如果下游的处理速度&#xff0c;比上游的输入数据小&#xff0c;就会导致程序处理慢&…...

爬虫知识--01

爬虫介绍 # 爬虫的概念&#xff1a; 通过编程技术(python:request,selenium)&#xff0c;获取互联网中的数据(app&#xff0c;小程序&#xff0c;网站)&#xff0c;数据清洗(xpaht&#xff0c;lxml)后存到库中(mysql&#xff0c;redis&#xff0c;文件&#xff0c;excel&#x…...

【Azure 架构师学习笔记】- Azure Databricks (7) --Unity Catalog(UC) 基本概念和组件

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Databricks】系列。 接上文 【Azure 架构师学习笔记】- Azure Databricks (6) - 配置Unity Catalog 前言 在以前的Databricks中&#xff0c;主要由Workspace和集群、SQL Warehouse组成&#xff0c; 这两年Databricks公…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

比较数据迁移后MySQL数据库和OceanBase数据仓库中的表

设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...