一.Spring事务
Mysql事务
在MySQL数据库中,事务(Transaction)是一组作为单个逻辑工作单元执行的SQL语句的集合。事务处理可以确保数据库从一种一致性状态转变为另一种一致性状态。如果事务中的所有SQL语句都成功执行,那么事务被提交(Commit),数据库的状态会永久地改变。如果因为某种原因,事务中的某个SQL语句失败,那么整个事务会被回滚(Rollback),数据库会回到事务开始之前的状态。简单介绍,事务是一组操作的集合,这组操作要么同时成功要么同时失败。
MySQL事务的常见操作包括:
- 开始事务:使用
START TRANSACTION
语句 - 提交事务:使用
COMMIT
语句 - 回滚事务:
ROLLBACK
语句来撤销事务中所做的所有更改
2.Spring事务
在spring中也有类似事务,使用注解@transactional
在程序运行时,spring会自动开启事务,运行结束后会自动提交事务
如果发生异常,会回滚事务
2.1事务属性
rollbackFor
回滚事物,默认情况下是runtimeexception 表示出现运行时异常回滚事务, 可以设置exception.class 表示出现任何异常都要回滚事物
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Autowired
private UserRepository userRepository; // 假设这是一个Spring Data JPA的仓库
@Transactional(rollbackFor = Exception.class)
public User saveUser(User user) {
try {
// 尝试保存用户到数据库
User savedUser = userRepository.save(user);
// 模拟一个可能发生的异常,这里使用了一个普通的Exception而不是RuntimeException
if (/* some condition that indicates an error */) {
throw new Exception("Error saving user");
}
// 如果一切顺利,方法正常结束,事务会自动提交
return savedUser;
} catch (Exception e) {
// 如果有任何异常(包括运行时异常和检查型异常),事务会被回滚
// 你可以在这里记录日志或执行其他清理操作
throw e; // 重新抛出异常,以便上层调用者可以处理它
}
}
}
在这个例子中,@Transactional(rollbackFor = Exception.class)
指定了即便发生了Exception
(或其子类)也应该回滚事务。这意味着,如果在saveUser
方法中抛出了任何Exception
,事务都会回滚,并且数据库中的更改不会被保存。
propagation
propagation属性定义了事务的传播行为,它决定了当一个事务方法被另一个事务方法调用时,事务应该如何处理。Spring定义了七种不同的事务传播行为,但其中最常用的有以下几种:
默认是required 表示存在事物时,加入事务,不存在事务,创建事物
requires_new 无论是否存在事务,都要创建新事务
举例说明
假设我们有两个服务方法,methodA
和methodB
,两者都被@Transactional
注解,但methodB
的propagation
属性被设置为Propagation.REQUIRES_NEW
。
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class MyService {
// 使用默认的事务传播行为 REQUIRED
@Transactional
public void methodA() {
// 执行操作...
// 调用methodB,由于methodB的事务传播行为是REQUIRES_NEW,
// 这里会暂停methodA的事务,并启动一个新的事务来执行methodB
methodB();
// methodB执行完毕后,其事务会提交或回滚,然后恢复methodA的事务继续执行
// ...
// 如果methodA之后还有操作,它们将在原来的事务中继续执行
}
// 使用REQUIRES_NEW事务传播行为
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
// 无论methodA的事务状态如何,这里都会开始一个新的事务
// 执行一些数据库操作...
// ...
// 如果methodB成功完成,它自己的事务会提交
// 如果methodB抛出未检查的异常,它自己的事务会回滚,但不影响methodA的事务(除非methodA也抛出异常)
}
}
二.AOP
1.什么是AOP
AOP (Aspect Oriented Programming, 面向切面编程) 是一种编程范式,它允许程序员将横切关注点从业务逻辑中分离出来。横切关注点通常包括日志记录、事务管理、安全性、性能监控等,这些关注点会跨越多个类和对象。通过使用AOP,这些关注点可以被模块化,并以声明的方式添加到代码中,从而提高了代码的可维护性和可重用性。
Aop 是面向切面编程,面向特定方法编程
在对目标方法不做惊动的情况下增强方法
AOP相关概念
连接点 可以被AOP控制的方法
切入点 需要增强的方法
通知 对于切入点表达式中的方法增强的共性内容
切面:切入点表达式和通知组成
在AOP中,切面(Aspect)是一个关注点模块化的实现,它包含了通知(Advice)和切点(Pointcut)的定义。通知定义了切面在何时以及如何应用其逻辑,而切点则定义了哪些连接点(Joinpoint)应该被切面所影响。
2.简单AOP实现
1.导入xml
2.定义Aop类
@Aspect标识切面类,由切入点表达式(指定增强哪些方法)+通知(增强的功能)组成
举例对某方法增强功能 计算方法耗时
@Aspect标注为切面类
@Component 交给ioc容器管理
@Around 表示环绕通知
在方法执行前后对原始方法增强包含切入点表达式,指定对哪些方法增强
3.AOP执行流程
1.启动spring
2.初始化bean对象
如果bean对象的方法匹配到切入点,创建目标对象的代理对象
如果没有匹配,创建普通bean对象
‘3.执行方法
如果bean是代理对象,执行增强的方法
如果不是,执行原有方法
4.通知类型
- 前置通知(Before advice):在目标方法执行之前执行的通知,无法阻止方法的继续执行(除非它抛出一个异常)。
- 后置通知(After returning advice):在目标方法成功执行之后执行的通知。如果目标方法通过抛出异常退出,则不会执行此类型的通知。
- 异常通知(After throwing advice):在目标方法通过抛出异常退出时执行的通知。通常用于记录异常信息或进行异常处理。
- 最终通知(After (finally) advice):无论目标方法通过何种方式退出(正常返回或异常退出),该通知都会执行。它类似于Java语言中的finally块。
- 环绕通知(Around advice):环绕通知是最强大的通知类型,它将目标方法封装起来,可以在方法调用之前和之后自定义行为,甚至可以完全控制是否调用目标方法。
补充关于@Around
1.执行原始方法 需要调用 ProceedingjoinPoint的proceed方法
2.返回值是用Object接收:由于在目标方法执行前后运行,可以拿到目标方法运行时返回值(调用proceed),返回值是用Object接收
5.多个切面类执行顺序
1.默认按照切面类名称字母排序
目标方法前的通知方法 字母靠前的先执行 如before
目标方法后的通知方法 字母靠前的后执行 如after
2.@Order(数字)指定顺序
目标方法前的通知方法 ,数字小的先执行 如before
目标方法后的通知方法 ,数字小的后执行 如after
6.切入点表达式
指定需要增强功能的目标方法
1.切入点表达式execution
*匹配方法名,包名,类名一部分,也可以匹配任意包名类名方法名,返回值,任意类型的一个参数
.. 匹配任意层级的包,任意类型,任意个数的参数
多个语句可以使用与或非符号连接
切入点表达式代码重复,抽取为一个切点pointcut
2.切入点表达式annotation
@annotation(注解全类名) 匹配表示特定注解的方法
1.创建一个自定义注解 Mylog
2.@Mylog加入需要的方法上
3.annotation(注解全类名)
总结
7.连接点
Spring中使用JoinPoint抽象连接点 获取方法返回值,签名,运行参数等
1.Around 通知 获取连接点使用 ProceedingJoinPoint
2.其它四种通知 获取连接点使用JoinPoint(是ProceedingJoinPoint父类型)