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语句也是很重要的. 如何通过代码操作数据库? 通过代码操作…...

C++操纵符用法
C中的操纵符(Manipulators)是用于格式化输入输出的特殊工具。它们可以在输出流中控制各种格式,如设置字段宽度、精度、填充字符等。以下是一些常用的操纵符及其用法: setw(int width): 设置字段宽度为width个字符。 cout <<…...

【一步一步了解Java系列】:子类继承以及代码块的初始化
看到这句话的时候证明:此刻你我都在努力 加油陌生人 个人主页:Gu Gu Study专栏:一步一步了解Java 喜欢的一句话: 常常会回顾努力的自己,所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 作者:小闭 …...

探索Expect Python用法:深入解析与实战挑战
探索Expect Python用法:深入解析与实战挑战 在自动化和脚本编写领域,Expect Python已经成为了一种强大的工具组合。它结合了Expect的交互式会话处理能力和Python的编程灵活性,为开发者提供了一种全新的方式来处理复杂的自动化任务。然而&…...

【PostgreSQL17新特性之-explain命令新增选项】
EXPLAIN是一个用于显示语句执行计划的命令,可用于显示以下语句类型之一的执行计划: - SELECT - INSERT - UPDATE - DELETE - VALUES - EXECUTE - DECLARE - CREATE TABLE AS - CREATE MATERIALIZED VIEWPostgreSQL17-beta1版本近日发布了,新…...

JAVA实现人工智能,采用框架SpringAI
文章目录 JAVA实现人工智能,采用框架SpringAISpring AI介绍使用介绍项目前提项目结构第一种方式采用openai1. pom文件: 2. application.yml 配置3.controller 实现层 项目测试 JAVA实现人工智能,采用框架SpringAI Spring AI介绍 Spring AI是AI工程师的一个应用框架…...

基础—SQL—DQL(数据查询语言)分组查询
一、引言 分组查询的关键字是:GROUP BY。 二、DQL—分组查询 1、语法 SELECT 字段列表 FROM 表名 [ WHERE 条件 ] GROUP BY 分组字段名 [ HAVING 分组后过滤条件 ]; 注意: 1、[ ] 里的内容可以有可以没有。 2、这条SQL语句有两块指定条件的地方&#…...

从CSV到数据库(简易)
需求:客户上传CSV文档,要求CSV文档内容查重/插入/更新相关数据。 框架:jdbcTemplate、commons-io、 DB:oracle 相关依赖: 这里本来打算用的2.11.0,无奈正式项目那边用老版本1.3.1,新版本对类型…...

K210视觉识别模块学习笔记3:内存卡写入拍摄图片_LED三色灯的操作_按键操作_定时器的配置使用
今日开始学习K210视觉识别模块: LED三色灯的操作_按键操作_定时器的配置使用_内存卡写入拍摄图片 亚博智能的K210视觉识别模块...... 固件库版本: canmv_yahboom_v2.1.1.bin 本文最终目的是编写一个按键拍照的例程序: 为以后的专用场景的模型训练做准备…...

如何定义“智慧校园”这个概念
在信息爆炸的时代,教育面临着前所未有的挑战:如何让每个学生在海量知识中找到属于自己的路径?如何让教师的智慧与科技的力量相得益彰?如何让校园成为培养创新思维的摇篮?智慧校园,这一概念的提出࿰…...

OpenSSL自签名证书
文章目录 生成1. 生成根证书的私钥(root_private_key.pem)2. 创建根证书的CSR和自签名证书(root_csr.pem)3. 生成服务器证书的私钥(server_private_key.pem)4. 创建服务器证书的CSR(server_priv…...