死磕Spring之AOP篇 - Spring 事务详解

该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读。

Spring 版本:5.1.14.RELEASE

在开始阅读 Spring AOP 源码之前,需要对 Spring IoC 有一定的了解,可查看我的 《死磕Spring之IoC篇 - 文章导读》 这一系列文章

了解 AOP 相关术语,可先查看 《Spring AOP 常见面试题) 》 这篇文章

该系列其他文章请查看:《死磕 Spring 之 AOP 篇 - 文章导读》

前序

前面我的一系列文章对 Spring AOP 进行了比较详细的讲述,相信你对 Spring AOP 有了更加深入的理解,如果你对于 Spring AOP 不是很了解,建议先查看我前面的一系列文章对 Spring AOP 有一定的了解,因为 Spring 事务是借助于 Spring AOP 实现的。由于这段时间有点忙(太懒了~),没能及时更新 Spring AOP 在 Spring 内部的应用相关内容,趁着还对 Spring AOP 有一点印象,我们一起来看看 Spring 事务的相关源码。我猜应该是比较容易理解的,因为已经有了 Spring AOP 的基础,相信对于 Spring 事务会“轻而易举”地掌握,嘻嘻~

我们先了解一下 Spring 事务里面的“物理事务”和“逻辑事务”,所谓的“物理事务”是指 JDBC 的事务,上一次事务和本次事务之间是没有其他事务的,在执行一条命令(默认行为自动提交)都会产生一个事务,如果把 autocommit 设置为 false,需要主动 commit 才完成一个事务。所谓的“逻辑事务”是 Spring 对 JDBC 的一个抽象,例如 Spring 默认的事务传播行为是 REQUIRED,当执行 @Transactional 注解标注的方法时,如果此时正处于一个事务(物理事务)中,那么加入到这个事务中,你可以理解为创建了一个“逻辑事务”,进行提交的时候不会执行 Connection 的 commit 方法,而是在外面的“物理事务”中进行 commit 时一并完成本次事务。

Spring 事务的传播级别

REQUIRED:默认传播级别,如果正处于一个事务中,则加入;否则,创建一个事务

SUPPORTS:如果正处于一个事务中,则加入;否则,不使用事务

MANDATORY:如果当前正处于一个事务中,则加入;否则,抛出异常

REQUIRES_NEW:无论如何都会创建一个新的事务,如果正处于一个事务中,会先挂起,然后创建

NOT_SUPPORTED:不使用事务,如果正处于一个事务中,则挂起,不使用事务

NEVER:不使用事务,如果正处于一个事务中,则抛出异常

NESTED:嵌套事务,如果正处于一个事务中,则创建一个事务嵌套在其中(MySQL 采用 SAVEPOINT 保护点实现的);否则,创建一个事务

关于 Spring 事务传播级别更多的细节在接下来的源码中进行讨论

Spring 事务的使用示例

相信看到这篇文章的你对于 @Transactional 注解的使用肯定非常了解,不过这里还是列举以下它的使用方式

Spring MVC

引入 Spring 事务相关依赖后,在 Spring MVC 中有两种(XML 配置和注解)驱动 Spring 事务的方式,如下面所示:

方式一:

<?xml version="1.0" encoding="UTF-8"?> <beans> <!-- 定义一个数据源 --> <bean>...</bean> <!-- 事务管理器 --> <bean> <!-- 指定数据源 --> <property ref="dataSource"/> </bean> <!-- 事务模块驱动,指定使用上面定义事务管理器,默认值为 transactionManager --> <tx:annotation-driven transaction-manager="txManager"/> </beans>

方式二:

需要在 Spring 能扫描的一个 Bean 上添加一个 @EnableTransactionManagement 注解,然后添加一个 TransactionManagementConfigurer 实现类,如下:

package tk.mybatis.simple.controller; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.TransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.TransactionManagementConfigurer; import javax.annotation.Resource; import javax.sql.DataSource; @Configuration @EnableTransactionManagement public class TransactionManagerConfig implements TransactionManagementConfigurer { @Resource DataSource dataSource; @Override public TransactionManager annotationDrivenTransactionManager() { // 返回一个事务管理器,设置数据源 return new DataSourceTransactionManager(dataSource); } }

此时你可以使用 @Transactional 注解标注在方法(或者类)上面,使得方法的执行处于一个事务中,如下:

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class}) public void update(){ try { // 数据库操作 } catch (Exeception e){ // 将事务状态设置为回滚 TransactionInterceptor.currentTransactionStatus().setRollbackOnly(); } } Spring Boot

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygsff.html