Spring事务管理、SpringAop

news2024/11/24 17:13:02

目录

​编辑

Spring事务管理

注解:@Transactional

rollbackFor

事务属性-传播行为

propagation

SpringAOP

 AOP核心概念

通知类型

通知顺序

切入点表达式

 切入点表达式-execution

切入点表达式-@annotation

连接点

​编辑

将案例中 增、删、改 相关接口的操作日志记录到数据库表中 


Spring事务管理

注解:@Transactional

位置:业务(service)层的方法上、类上、接口上
作用:将当前方法交给spring进行事务管理,方法执行前,开启事务;成功执行完毕,提交事务;出现异常,回滚事务

配置文件

#spring事务管理日志
logging:
  level:
    org.springframework.jdbc.support.JdbcTransactionManager: debug
 @Transactional//spring事务管理
    @Override
    public void delete(Integer id) {
        deptMapper.deleteById(id);//根据id删除部门数据
        int a=1/0;//模拟异常
        empMapper.deleteById(id);根据部门ID删除该部门下的员工
    }

 

 不加@Transactional这个注解的话,出现了异常之后,只删除了部门的数据,该部门下的员工数据并没有被删除

rollbackFor

默认情况下,只有出现 RuntimeException 才回滚异常。rolbackFor属性用于控制出现何种异常类型,回滚事务

如果异常是这样的话,是不会回滚事务的,部门数据还是被删除了 

而之前属于算数异常

算数异常父类是 RuntimeException

这样就可以了

事务属性-传播行为

propagation

事务传播行为:指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行事务控制。 

REQUIRED        【默认值】需要事务,有则加入,无则创建新事务
REQUIRES_NEW        需要新事务,无论有无,总是创建新事务
SUPPORTS        支持事务,有则加入,无则在无事务状态中运行
NOT SUPPORTED       不支持事务,在无事务状态下运行,如果当前存在已有事务,则挂起当前事务
MANDATORY        必须有事务,否则抛异常
NEVER        必须没事务,否则抛异常

REQUIRED:大部分情况下都是用该传播行为即可

REQUIRES_NEW:当我们不希望事务之间相互影响时,可以使用该传播行为。比如:下订单前需要记录日志,不论订单保存成功与否,都需要保证日志记录能够记录成功。 

SpringAOP

快速入门:统计各个业务层方法执行耗时 

导入依赖:在pom.xml中导入AOP的依赖

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

编写AOP程序:针对于特定方法根据业务需要进行编程

package com.example.Aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@Aspect//Aop类
public class TimeAspect {
    @Around("execution(* com.example.Service.*.*(..))")//切入点表达式
    public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {
        //记录开始时间
        long begin = System.currentTimeMillis();
        //调用原始方法运行
        Object result = joinPoint.proceed();
        //记录结束时间,计算方法的执行耗时
        long end = System.currentTimeMillis();
        log.info(joinPoint.getSignature() +"方法执行耗时:{}ms",end-begin);

        return result;
    }
}

 AOP核心概念

连接点:JoinPoint,可以被AOP控制的方法(暗含方法执行时的相关信息)

通知类型

@Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行
@Before:前置通知,此注解标注的通知方法在目标方法前被执行
@After :后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行

@AfterReturning :返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行

@AfterThrowing :异常后通知,此注解标注的通知方法发生异常后执行

 可以用@Pointcut优化一下

@PointCut
该注解的作用是将公共的切点表达式抽取出来,需要用到时引用该切点表达式即可。 

 

private:仅能在当前切面类中引用该表达式

public:在其他外部的切面类中也可以引用该表达式

注意 

@Around环绕通知需要自己调用 ProceedingJoinPoint.proceed()来让原始方法执行,其他通知不需要考虑目标方法执行

@Around环绕通知方法的返回值,必须指定为0bject,来接收原始方法的返回值。

通知顺序

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

1.不同切面类中,默认按照切面类的类名字母排序:

目标方法前的通知方法:字母排名靠前的先执行

目标方法后的通知方法:字母排名靠前的后执行

2.用 @Order(数字)加在切面类上来控制顺序

目标方法前的通知方法:数字小的先执行

目标方法后的通知方法:数字小的后执行 

切入点表达式

切入点表达式:描述切入点方法的一种表达式作用:主要用来决定项目中的哪些方法需要加入通知
常见形式:
1. execution(.):根据方法的签名来匹配
2.@annotation(…):根据注解匹配

 切入点表达式-execution

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

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

其中带?的表示可以省略的部分
访问修饰符:可省路(比如:public、protected)
包名.类名: 可省略(不建议省略)
throws 异常:可省略(注意是方法上声明抛出的异常,不是实际抛出的异常)

可以使用通配符描述切入点

单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数,也可以通配包、类、方法名的一部分

execution(* com.*.service.*.update*(*))

多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数

execution(* com.example..DeptService.*(..))

 就是通配DeptService接口下的所有方法,但是要求这个方法的返回值必须是void,而且这个方法中必须有一个Integer类型的参数

书写建议:

所有业务方法名在命名时尽量规范,方便切入点表达式快速匹配。如:查询类方法都是 find 开头,更新类方法都是 update开头

描述切入点方法通常基于接口描述,而不是直接描述实现类,增强拓展性。

在满足业务需要的前提下,尽量缩小切入点的匹配范围。如:包名匹配尽量不使用…,使用*匹配单个包,。

切入点表达式-@annotation

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

先自定义一个注解

这就简化了

 

连接点

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

  • 对于 @Around 通知,获取连接点信息只能使用ProceedingJoinPoint
  • 对于其他四种通知,获取连接点信息只能使用 JoinPoint, 它是 ProceedingJoinPoint 的父类型

around类型 

before类型 

将案例中 增、删、改 相关接口的操作日志记录到数据库表中 

自定义注解

package com.example.Anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Log {
}

 定义切面类

package com.example.Aop;

import com.alibaba.fastjson.JSONObject;
import com.example.Mapper.OperateLogMapper;
import com.example.Pojo.OperateLog;
import com.example.Utils.JwtUtils;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Arrays;

@Slf4j
@Component
@Aspect//切面类
public class LogAspect {
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private OperateLogMapper operateLogMapper;
    @Around("@annotation(com.example.Anno.Log)")
    public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
        //操作人id--当前登录员工
        //获取请求头中的jwt令牌,解析令牌
        String jwt = request.getHeader("token");
        Claims claims = JwtUtils.parseJWT(jwt);
        Integer operateUser =(Integer) claims.get("id");
        //操作时间
        LocalDateTime operateTime = LocalDateTime.now();
        //操作类名
        String className = joinPoint.getTarget().getClass().getName();
        //操作方法名
        String methodName = joinPoint.getSignature().getName();
        //操作方法传入的参数
        Object[] args = joinPoint.getArgs();
        String methodParams = Arrays.toString(args);

        long begin = System.currentTimeMillis();
        //调用原始目标方法运行
        Object result = joinPoint.proceed();
        long end = System.currentTimeMillis();
        //方法的返回值
        String returnValue = JSONObject.toJSONString(result);

        //操作耗时
        long costTime = end - begin;

        //记录日志
        OperateLog operateLog=new OperateLog(null,operateUser,operateTime,className,methodName,methodParams,returnValue,costTime);
        operateLogMapper.insert(operateLog);
        log.info("AOP记录操作日志:{}",operateLog);
        return result;
    }
}

还要在增删改操作上加上自定义注解@Log


努力遇见更好的自己!!!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1830250.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

unity跑酷游戏(源码)

包括&#xff1a;触发机关&#xff0c; 优化 fog的调试 效果 碰到障碍物游戏时间暂停&#xff08;挂载到障碍物上&#xff09; 上面需要有碰撞体 游戏物体上需要有标签 using System.Collections; using System.Collections.Generic; using UnityEngine;public class Barri…

【仿真建模-anylogic】FlowchartBlock原理解析

Author&#xff1a;赵志乾 Date&#xff1a;2024-06-17 Declaration&#xff1a;All Right Reserved&#xff01;&#xff01;&#xff01; 1. 类图 2. 原理解析 2.1 核心函数 函数功能FlowchartBlock(Engine engine ,Agent owner, AgentList population )构造函数&#xff…

C语言王国——深入自定义类型(结构体)

目录 一、引言 二、结构体 1. 结构体类型的声明 2. 结构体变量的创建和初始化 2.1 创建 2.2 初始化 2.3 typedef 2.4 特殊声明 2.5 自引用 3. 结构成员访问操作符 4. 结构体内存对齐 4.1 对齐规则 4.2 offsetof 4.3 为什么存在内存对齐 5. 结构体传参 6. 结构体实现…

仅靠独立网站也能赚到100万,真的太牛了

你听说过 Photopea 吗&#xff1f;这是一个免费的类似 Photoshop 的图像编辑器。 这个项目&#xff1a; 每月1300万访问量每月150万用户使用小时每月10万美元的广告收入 Photopea 项目的天才创造者是 Ivan Kutskir。 令人惊讶的是&#xff0c;他独自处理了每日50万用户&…

数组趣味玩法:在Java SE中尝试创新玩法

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

C++ | Leetcode C++题解之第160题相交链表

题目&#xff1a; 题解&#xff1a; class Solution { public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {if (headA nullptr || headB nullptr) {return nullptr;}ListNode *pA headA, *pB headB;while (pA ! pB) {pA pA nullptr ? headB : p…

【Vue3】插槽的使用及其分类

历史小剧场 后来我才明白&#xff0c;造反的宋江&#xff0c;和招安的宋江&#xff0c;始终是同一个人。 为什么要造反&#xff1f; 造反&#xff0c;就是为了招安。 ----《明朝那些事儿》 概念 在日常的项目开发中&#xff0c;当我们在编写一个完整的组件时&#xff0c;不可避…

款基于SpringBoot+Vue+ElementUI技术栈开发的自定义表单工具(已开源)

TDuck填鸭表单是一个开源的问卷调查系统&#xff0c;一款基于SpringBootVueElementUI技术栈开发的自定义表单工具&#xff0c;它不仅支持问卷调查&#xff0c;还能进行数据收集。TDuck团队经过两年的优化&#xff0c;使得社区版功能趋于稳定。2023年5月&#xff0c;团队推出了可…

flstudio怎么调中文

FL Studio设置中文的步骤如下&#xff1a; 打开FL Studio&#xff1a;首先&#xff0c;需要打开FL Studio编曲软件。 进入常规设置&#xff1a;在软件顶部菜单栏中&#xff0c;选择“OPTIONS”&#xff0c;然后点击“General setting”&#xff0c;进入常规设置窗口。 切换语言…

Centos部署openGauss6.0创新版本,丝滑的体验

作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、MySQL、PG、高斯及Greenplum备份恢复&#xff0c; 安装迁移&#xff0c;性能优化、故障…

Pytest框架中fixture功能详解

文章目录 1 定义 Fixture函数 2 Fixture 的函数参数 2.1 传入其他fixture函数作为参数 2.2 传入request对象参数 示例1&#xff1a;访问fixture的调用者 示例2&#xff1a;使用fixture的参数 3 Fixture 的作用域参数scope 3.1 scopeclass场景 3.2 scopesession场景 4…

ImageNet-1k 测试集 两大坑

1、官方网站提交test set标签时&#xff0c;千万不能提交zip文件&#xff0c;即便明文说可以 https://image-net.org/challenges/LSVRC/eval_server.php 不然就会浪费一次提交机会&#xff0c;直接提交submission.txt就可以&#xff0c;注意每排5个预测结果&#xff0c;用于计…

Excel报表

(Apache POI) 入门案例 P164 使用POI需要导入下面2个坐标&#xff1a; <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId> </dependency> <dependency><groupId>org.apache.poi</groupId>&…

[个人感悟] 缓存应该考察哪些问题?

前言 缓存, 根据冯诺依曼计算机模型, 无非是为了更高效的交互, 使用内存IO替换本地磁盘IO. 又因为内存的稀缺性, 其必然存储的是热点数据, 且较小的数据. [虽然直至今日, 已有使用缓存作为数据库的使用, 但是与磁盘IO相比, 其价格仍是数倍之多.] 当涉及缓存问题时, 又分为本地…

springboot+vue+mybatis教师工作审核系统+PPT+论文+讲解+售后

随着社会不断进步与发展&#xff0c;生活节奏不断加快&#xff0c;信息已经成为我们生活中不可缺少的一部分&#xff0c;很多学校需要掌握大量的信息来了解特定学生的需求&#xff0c;传统的做法是组织大量的人力物力对学生散发调查表&#xff0c;然后对收集的信息进行统计并得…

【SOEM主站】EtherCAT主站时钟偏移补偿

在进行EtherCAT主从通讯测试时&#xff0c;比较容易在DC配置出现错误&#xff0c;特别是使用到从站DC模式时&#xff0c;有时会报同步错误&#xff0c;有时即使没报错误伺服从站运行过程中也会出现电机轴的抖动。引起同步错误其中一个原因就是主站发送数据帧时间存在较大的抖动…

一文带你精通Android中的Activity

本文将会从活动的生命周期、启动模式、Intent数据传输、最佳实践等多维度来讲解Activity&#xff0c;希望对你有用 生命周期 深入理解活动的生命周期&#xff0c;可以帮助我们更加流畅地编程&#xff0c;并在管理系统资源方面更加游刃有余 活动状态 每个活动在生命周期中最…

《Windows API每日一练》4.4 绘制填充区域

本节讲述如何填充由线条构建的封闭区域。当我们初始化一个窗口类时&#xff0c;往往已经指定了窗口的背景色画刷&#xff08;WHITE_BRUSH&#xff09;&#xff0c;即默认的填充封闭区域背景的画刷。如果我们想更换背景颜色&#xff0c;需要选入其他系统预定义的画刷&#xff08…

助力樱桃智能自动化采摘,基于YOLOv5全系列【n/s/m/l/x】参数模型开发构建果园种植采摘场景下樱桃成熟度智能检测识别系统

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;技术已经渗透到我们生活的方方面面&#xff0c;从智能家居到自动驾驶&#xff0c;再到医疗健康&#xff0c;其影响力无处不在。然而&#xff0c;当我们把目光转向中国的农业领域时&#xff0c;一个令人惊讶的…

几何公差的设计和选用

保证轴承的旋转精度&#xff0c;提出圆柱度&#xff1b; 这里的轴肩部面 为了测量方便&#xff0c;使用圆跳动代替垂直度公差方便一些。