SpringBoot的第二大核心AOP系统梳理
目录
1 事务管理
1.1 事务
1.2 @Transactional注解
1.2.1 rollbackFor
1.2.2 propagation
2 AOP 基础
2.1 AOP入门
2.2 AOP核心概念
3. AOP进阶
3.1 通知类型
3.2 通知顺序
3.3 切入点表达式
execution切入点表达式
@annotion注解
3.4 连接点
1 事务管理
1.1 事务
事务是一组操作的集合,它是一个不可分割的工作单位。事务会把所有的操作作为一个整体,一起向数据库提交或者是撤销操作请求。所以这组操作要么同时成功,要么同时失败。
事务的目标:保证操作前后,数据的一致性。
事务的操作主要有三步:
-
开启事务(一组操作开始前,开启事务):start transaction / begin ;
-
提交事务(这组操作全部成功后,提交事务):commit ;
-
回滚事务(中间任何一个操作出现异常,回滚事务):rollback ;
1.2 @Transactional注解
在当前方法执行之前来开启事务,方法执行完毕后提交事务。如果在方法执行过程中出现异常,就会进行事务的回滚操作。
我们一般会在service层控制事务,因为一个业务功能可能会包含多个数据访问操作。在sevice层控制事务,我们就可以将多个数据访问操作控制在一个事务范围内。
@Transactional注解书写位置:
-
方法 (当前方法交给spring进行事务管理)
-
类 (当前类中所有的方法都交由spring进行事务管理)
-
接口 (接口下所有的实现类当中所有的方法都交给spring 进行事务管理)
说明:在application.yml配置文件中开启事务管理日志,可以在console看到和事务相关的日志信息

@Transactional注解的两个常见属性:
-
异常回滚的属性:rollbackFor
-
事务传播行为:propagation
1.2.1 rollbackFor
默认情况下,只有出现RuntimeException(运行时异常)才会回滚事务。
如果需要指定出现某种异常时回滚事务,需要配置@Transactional注解中的rollbackFor属性。
@Transactional(rollbackFor=Exception.class)
1.2.2 propagation
propagation作用:配置事务的传播行为
在A方法运行的时候,首先会开启一个事务,在A方法当中又调用了B方法, B方法自身也是事务,那么B方法在运行的时候,到底是加入到A方法的事务当中来,还是B方法在运行的时候新建一个事务?
解决方案:给B方法加上注解
@Transactional(propagation = Propagation.REQUIRES_NEW)//不论A是否有事务,都新建事务
| 属性值 | 含义 |
|---|---|
| REQUIRED | 【默认值】B方法加入到A的事务中。 |
| REQUIRES_NEW | 为B创建新事务。即使A运行异常需要回滚,也不影响B的事务提交。 |
2 AOP 基础
2.1 AOP入门
AOP(Aspect Oriented Programming,面向切面编程)就是面向特定方法编程,是一种编程思想。
AOP的作用:在程序运行期间在不修改源代码的基础上对已有方法进行功能增强(无侵入性: 解耦)

AOP的优势:
-
减少重复代码
-
提高开发效率
-
维护方便
实现步骤:
-
导入依赖:在pom.xml中导入AOP的依赖
-
编写AOP程序:给特定方法增强功能
pom.xml
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
@Component//标注一个类为Spring容器的Bean
@Aspect //当前类为切面类
@Slf4j//日志框架
public class TimeAspect {@Around("execution(* com.itheima.service.*.*(..))") public Object recordTime(ProceedingJoinPoint pjp) throws Throwable {//记录方法执行开始时间long begin = System.currentTimeMillis();//执行原始方法Object result = pjp.proceed();//记录方法执行结束时间long end = System.currentTimeMillis();//计算方法执行耗时log.info(pjp.getSignature()+"执行耗时: {}毫秒",end-begin);return result;}
}
AOP常见的应用场景:
-
统计各个业务层方法的执行耗时
-
记录系统的操作日志
-
权限控制
-
事务管理:我们前面所讲解的Spring事务管理,底层其实也是通过AOP来实现的,只要添加@Transactional注解之后,AOP程序自动会在原始方法运行前先来开启事务,在原始方法运行完毕之后提交或回滚事务
2.2 AOP核心概念
1. 连接点:JoinPoint,所有可以被AOP控制的方法
2. 通知:Advice,控制连接点的方法,比如上面的recordTime()方法
3. 切入点:PointCut,execution里的方法,通知仅会在切入点方法执行时被应用
假如切入点表达式改为DeptServiceImpl.list(),就代表只有list()方法运行时才会应用通知。
4. 切面:Aspect,通知+切入点
通过切面能够描述当前AOP程序针对哪个原始方法(连接点),在什么条件下(切入点表达式)执行什么样的操作(通知)。
切面所在的类,我们一般称为切面类(被@Aspect注解标识的类),比如上面的TimeAspect类。

5. 目标对象:Target,连接点方法所属的类

Spring的AOP底层是基于动态代理实现的,即在程序运行时,会自动为目标对象生成对应的代理对象。在代理对象中按照通知对目标对象中的原始方法进行功能增强。然后将代理对象注入到Controller层。
3. AOP进阶
3.1 通知类型
-
@Around:环绕通知,通知方法在目标方法前、后都被执行。
-
@Before:前置通知,通知方法在目标方法前被执行
-
@After :后置通知,通知方法在目标方法后被执行,无论是否有异常都会执行
-
@AfterReturning : 返回后通知,通知方法在目标方法正常执行后被执行
-
@AfterThrowing : 异常后通知,此注解标注的通知方法发生异常后执行
在使用@Around环绕通知时的注意事项:
-
原始方法如果执行时有异常,环绕通知中的后置代码不会在执行了
-
@Around环绕通知需要自己调用 ProceedingJoinPoint.proceed() 来让原始方法执行,其他通知不需要考虑目标方法执行
-
@Around环绕通知方法的返回值必须指定为Object。来接收原始方法的返回值,否则原始方法执行完毕,是获取不到返回值的。
@PointCut注解:作用是将公共的切入点表达式抽取出来,需要用到时引用该切入点表达式即可。
@Slf4j
@Component
@Aspect
public class MyAspect1 {//切入点方法(公共的切入点表达式)@Pointcut("execution(* com.itheima.service.*.*(..))")private void pt(){}//前置通知(引用切入点)@Before("pt()")public void before(JoinPoint joinPoint){log.info("before ...");}//环绕通知@Around("pt()")public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {log.info("around before ...");//调用目标对象的原始方法执行Object result = proceedingJoinPoint.proceed();//如果原始方法在执行时发生异常,则后续代码不在执行log.info("around after ...");return result;}
}
注意:当切入点方法使用private修饰时,仅能在当前切面类中引用该表达式, 当外部其他切面类也要引用当前类中的切入点表达式时,需要把private改为public,而在引用的时候,具体的语法为:全类名.方法名()。
3.2 通知顺序
定义了多个切面类,而多个切面类中多个切入点都匹配到了同一个目标方法。此时当目标方法在运行的时候,这多个切面类当中的这些通知方法都会运行。哪个先运行,哪个后运行?
在不同切面类中,默认按照切面类的类名字母排序:
-
目标方法@Before方法:字母排名靠前的先执行
-
目标方法@After方法:字母排名靠前的后执行
@Order注解:控制通知的执行顺序
@Slf4j
@Component
@Aspect
@Order(2) //切面类的执行顺序(前置通知:数字越小先执行; 后置通知:数字越小越后执行)
public class MyAspect2 {//通知
}
3.3 切入点表达式
作用:主要用来决定项目中的哪些方法需要加入通知
execution切入点表达式
示例:
execution(void com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))
execution(* com..DeptServiceImpl.delete(java.lang.Integer))
execution(* com..*.*(..))
//匹配DeptServiceImpl类中以find开头的方法
execution(* com.itheima.service.impl.DeptServiceImpl.find*(..))
描述切入点方法通常基于接口描述,而不是直接描述实现类,增强拓展性
@annotion注解
新建一个注解(跟新建类的方式一样);
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
}
然后在目标方法上添加注解@MyLog,表示该方法被通知方法控制;
最后在切面类中的通知方法添加@annotation注解,括号里的参数为MyLog的全名。
@Slf4j
@Component
@Aspect
public class MyAspect6 {//前置通知@Before("@annotation(com.itheima.anno.MyLog)")public void before(){log.info("MyAspect6 -> before ...");}
}
当一个新的方法需要被该通知方法控制时,在新方法上添加注解@MyLog即可。
3.4 连接点
在Spring中用JoinPoint抽象了连接点,用它可以获得方法执行时的相关信息,如目标类名、方法名、方法参数等。
-
对于@Around通知,获取连接点信息只能使用ProceedingJoinPoint类型
-
对于其他四种通知,获取连接点信息只能使用JoinPoint,它是ProceedingJoinPoint的父类型
@Slf4j
@Component
@Aspect
public class MyAspect7 {@Pointcut("@annotation(com.itheima.anno.MyLog)")private void pt(){}//前置通知@Before("pt()")public void before(JoinPoint joinPoint){log.info(joinPoint.getSignature().getName() + " MyAspect7 -> before ...");}//后置通知@Before("pt()")public void after(JoinPoint joinPoint){log.info(joinPoint.getSignature().getName() + " MyAspect7 -> after ...");}//环绕通知@Around("pt()")public Object around(ProceedingJoinPoint pjp) throws Throwable {//获取目标类名String name = pjp.getTarget().getClass().getName();log.info("目标类名:{}",name);//目标方法名String methodName = pjp.getSignature().getName();log.info("目标方法名:{}",methodName);//获取方法执行时需要的参数Object[] args = pjp.getArgs();log.info("目标方法参数:{}", Arrays.toString(args));//执行原始方法Object returnValue = pjp.proceed();return returnValue;}
}
相关文章:
SpringBoot的第二大核心AOP系统梳理
目录 1 事务管理 1.1 事务 1.2 Transactional注解 1.2.1 rollbackFor 1.2.2 propagation 2 AOP 基础 2.1 AOP入门 2.2 AOP核心概念 3. AOP进阶 3.1 通知类型 3.2 通知顺序 3.3 切入点表达式 execution切入点表达式 annotion注解 3.4 连接点 1 事务管理 1.1 事务…...
react、vue动态form表单
需求在日常开发中反复写form 是一种低效的开发效率,布局而且还不同这就需要我们对其封装 为了简单明了看懂代码,我这里没有组件,都放在一起,简单抽离相信作为大佬的你,可以自己完成, 一、首先我们做动态f…...
halcon程序如何导出C#文件
1.打开halcon文件; 2.写好需要生成C#文件的算子或函数; 3.找到档案-输出,如下图; 4.点击输出,弹出如下窗口 (1)可以修改导出文件的存储路径 (2)选择C#-HALCON/.NET &…...
RabbitMQ三、springboot整合rabbitmq(消息可靠性、高级特性)
一、springboot整合RabbitMQ(jdk17)(创建两个项目,一个生产者项目,一个消费者项目) 上面使用原生JAVA操作RabbitMQ较为繁琐,很多的代码都是重复书写的,使用springboot可以简化代码的…...
第八十九周周报
学习目标: 论文 学习时间: 2024.05.25-2024.05.31 学习产出: 一、论文 SAN: INDUCING METRIZABILITY OF GAN WITH DISCRIMINATIVE NORMALIZED LINEAR LAYER 将GAN与切片最优输运联系起来,提出满足方向最优性、可分离性和单射…...
Centos升级Openssh版本至openssh-9.3p2
一、启动Telnet服务 为防止升级Openssh失败导致无法连接ssh,所以先安装Telnet服务备用 1.安装telnet-server及telnet服务 yum install -y telnet-server* telnet 2.安装xinetd服务 yum install -y xinetd 3.启动xinetd及telnet并做开机自启动 systemctl enable…...
茉莉香飘,奶茶丝滑——周末悠闲时光的绝佳伴侣
周末的时光总是格外珍贵,忙碌了一周的我们,终于迎来了难得的闲暇。这时,打开喜欢的综艺,窝在舒适的沙发里,再冲泡一杯香飘飘茉莉味奶茶,一边沉浸在剧情的海洋中,一边品味着香浓丝滑的奶茶&#…...
揭秘:Java字符串对象的内存分布原理
先来看看下面寄到关于String的真实面试题,看看你废不废? String str1 "Hello"; String str2 "Hello"; String str3 new String("Hello"); String str4 new String("Hello");System.out.println(str1 str2)…...
Vue.js - 生命周期与工程化开发【0基础向 Vue 基础学习】
文章目录 Vue 的生命周期Vue 生命周期的四个阶段Vue 生命周期函数(钩子函数 工程化开发 & 脚手架 Vue CLI**开发 Vue 的两种方式:**脚手架目录文件介绍项目运行流程组件化开发 & 根组件App.vue 文件(单文件组件)的三个组成…...
Element-UI 快速入门指南
Element-UI 快速入门指南 Element-UI 是一套基于 Vue.js 的桌面端组件库,由饿了么前端团队开发和维护。它提供了丰富的 UI 组件,帮助开发者快速构建美观、响应式的用户界面。本篇文章将详细介绍 Element-UI 的安装、配置和常用组件的使用方法,帮助你快速上手并应用于实际项…...
2024华为OD机试真题-整型数组按个位值排序-C++(C卷D卷)
题目描述 给定一个非空数组(列表),其元素数据类型为整型,请按照数组元素十进制最低位从小到大进行排序, 十进制最低位相同的元素,相对位置保持不变。 当数组元素为负值时,十进制最低位等同于去除符号位后对应十进制值最低位。 输入描述 给定一个非空数组,其元素数据类型…...
善听提醒遵循易经原则。世界大同只此一路。
如果说前路是一个大深坑,那必然是你之前做的事情做的不太好,当坏的时候,坏的结果来的时候,是因为你之前的行为,你也就不会再纠结了,会如何走出这个困境,是好的来了,不骄不躁…...
CrossOver有些软件安装不了 用CrossOver安装软件后如何运行
CrossOver为用户提供了三种下载软件的方式分别是:搜索、查找分类、导入。如果【搜索】和【查找分类】提供的安装资源不能成功安装软件,那么我们可以通过多种渠道下载安装包,并将安装包以导入的方式进行安装。这里我们以QQ游戏为例,…...
在vue中如何使用leaflet图层展示地图
在vue中如何使用leaflet <template><div id"map" class"map"></div> </template><script> export default {data () {return {};},mounted(){this.initMaps()},methods: {initMaps () {const map L.map(map, {zoomControl…...
mybatisplus 字段存的是json 在查询的时候怎么映射成对象
数据库交互对象 TableName(value "表名", autoResultMap true)TableField(typeHandler JacksonTypeHandler.class, value "user_info")private User user;autoResultMap 是一个 MyBatis-Plus 中的注解属性,用于控制是否自动生成结果映射。…...
Python 学习笔记【1】
此笔记仅适用于有任一编程语言基础,且对面向对象有一定了解者观看 文章目录 数据类型字面量数字类型数据容器字符串列表元组 type()方法数据类型强转 注释单行注释多行注释 输出基本输出连续输出,中间用“,”分隔更复杂的输出格式 变量定义del方法 标识符…...
Git系列:rev-parse 使用技巧
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…...
【Java数据结构】详解LinkedList与链表(一)
🔒文章目录: 1.❤️❤️前言~🥳🎉🎉🎉 2.ArrayList的缺陷 3.链表的概念及结构 4.无头单向非循环链表的实现 4.1成员属性 4.2成员方法 createList display——打印链表 addFirst——头插 addLast…...
PDF高效编辑器革新:一键智能转换PDF至HTML,轻松开启文件处理全新时代!
信息爆炸的时代,PDF文件因其跨平台、不易修改的特性,成为了商务、教育、出版等领域不可或缺的文件格式。然而,PDF文件的固定性也带来了诸多不便,特别是在需要对其内容进行编辑或格式转换时。这时,一款高效、易用的PDF编…...
JDBC知识
JDBC是什么? 这工作中我们针对数据库的操作,实际上很少会用到SQL语句,通过命令行/图形化来操作数据库,更多的是通过主流的编程语言来对数据库进行操作,即使通过代码来操作数据,我们还是会使用到SQL语句,所以掌握SQL语句也是很重要的. 如何通过代码操作数据库? 通过代码操作…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
