本篇来讲一下SpringBoot是怎么自动开启事务的,我们先来回顾一下以前SSM中是如何使用事务的

SSM使用事务

导入JDBC依赖包

众所周知,凡是需要跟数据库打交道的,基本上都要添加jdbc的依赖,在Spring项目中,加入的是spring-jdbc依赖:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>

配置版事务

在使用配置文件的方式中,通常会在Spring的配置文件中配置事务管理器,并注入数据源:

<!-- 注册数据源 -->
<bean id="dataSource" class="...">
<property name="" value=""/>
</bean> <!-- 注册事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean> <!-- 开启事务注解 -->
<tx:annotation-driven transaction-manager="txManager" />

接下来可以直接在业务层Service的方法上或者类上添加@Transactional

注解版事务

首先需要注册两个Bean,分别对应上面Spring配置文件中的两个Bean:

@EnableTransactionManagement//重要
@Configuration
public class TxConfig { @Bean
public DataSource dataSource() {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("...");
dataSource.setPassword("...");
dataSource.setDriverClass("...");
dataSource.setJdbcUrl("...");
return dataSource;
} //重要
@Bean
public PlatformTransactionManager platformTransactionManager() {
return new DataSourceTransactionManager(dataSource());//放入数据源
}
}

我们看到往Spring容器中注入了DataSource 和PlatformTransactionManager 对象,并且通过@EnableTransactionManagement注解开启了事务,和上面的XML配置是一一对应的。PlatformTransactionManager这个Bean非常重要,要使用事务管理,就必须要在IOC容器中注册一个事务管理器。

public interface PlatformTransactionManager {
//获取一个Transaction
TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;
//提交事务
void commit(TransactionStatus var1) throws TransactionException;
//回滚事务
void rollback(TransactionStatus var1) throws TransactionException;
}

我们看到事务管理器的作用就是获取事务,提交回滚事务。DataSourceTransactionManager是PlatformTransactionManager的一个实现类,大家可以看看我以前的文章spring5 源码深度解析----- Spring事务 是怎么通过AOP实现的?(100%理解Spring事务) 看一下Spring的声明式事务的源码。下面我们来看看SpringBoot是如何自动配置事务的

SpringBoot自动配置事务

引入JDBC

众所周知,在SpringBoot中凡是需要跟数据库打交道的,基本上都要显式或者隐式添加jdbc的依赖:

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

也就是jdbc的场景启动器,我们点进去看看

其实也是引入了spring-jdbc的依赖,接下来我们要看两个重要的事务自动配置类

DataSourceTransactionManagerAutoConfiguration

我们看到在spring.factories中配置了事务管理器自动配置类DataSourceTransactionManagerAutoConfiguration,我们进去看看

 @Configuration
//在类路径下有这个类存在PlatformTransactionManager时,这个配置类才会生效
//而前面我们已经引入了spring-boot-starter-jdbc,那自然是存在了
@ConditionalOnClass({ JdbcTemplate.class, PlatformTransactionManager.class })
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceTransactionManagerAutoConfiguration { @Configuration
@ConditionalOnSingleCandidate(DataSource.class)
static class DataSourceTransactionManagerConfiguration { private final DataSource dataSource; private final TransactionManagerCustomizers transactionManagerCustomizers; DataSourceTransactionManagerConfiguration(DataSource dataSource,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
this.dataSource = dataSource;
this.transactionManagerCustomizers = transactionManagerCustomizers
.getIfAvailable();
} @Bean
//没有当Spring容器中不存在PlatformTransactionManager这个对象时,创建DataSourceTransactionManager
//也就是如果我们自定义了DataSourceTransactionManager并注入Spring容器,这里将不会执行
@ConditionalOnMissingBean(PlatformTransactionManager.class)
public DataSourceTransactionManager transactionManager(DataSourceProperties properties) {
//创建DataSourceTransactionManager注入Spring容器,并且把dataSource传进去
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(this.dataSource);
if (this.transactionManagerCustomizers != null) {
this.transactionManagerCustomizers.customize(transactionManager);
}
return transactionManager;
} } }

很明显只要我们导入了spring-boot-starter-jdbc场景启动器,并且我们没有自定义DataSourceTransactionManager,那么事务管理器自动配置类DataSourceTransactionManagerAutoConfiguration会自动为我们创建DataSourceTransactionManager并注入Spring容器中。但是这还不够,我们前面还是需要通过@EnableTransactionManagement开启事务呢,如果不开启事务,@Transactional是不起任何作用的。下面我们就来看看是如何开启事务的

TransactionAutoConfiguration

我们看到在spring.factories中配置了事务自动开启配置类TransactionAutoConfiguration,我们进去看看

 @Configuration
//和DataSourceTransactionManagerAutoConfiguration中是一样的
//引入了spring-boot-starter-jdbc,那自然是存在了PlatformTransactionManager
@ConditionalOnClass({PlatformTransactionManager.class})
//这个自动配置类必须要在DataSourceTransactionManagerAutoConfiguration这个自动配置类之后才能生效
//也就是前面我们已经往Spring容器中注入了DataSourceTransactionManager这个对象才执行这个配置类
@AutoConfigureAfter({JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class})
@EnableConfigurationProperties({TransactionProperties.class})
public class TransactionAutoConfiguration {
public TransactionAutoConfiguration() {
} @Configuration
@ConditionalOnBean({PlatformTransactionManager.class})
@ConditionalOnMissingBean({AbstractTransactionManagementConfiguration.class})
public static class EnableTransactionManagementConfiguration {
public EnableTransactionManagementConfiguration() {
} @Configuration
//重点:通过 @EnableTransactionManagement注解开启事务
//可以看到和我们自己使用@EnableTransactionManagement是一样的
@EnableTransactionManagement(
proxyTargetClass = true
)
@ConditionalOnProperty(
prefix = "spring.aop",
name = {"proxy-target-class"},
havingValue = "true",
matchIfMissing = true
)
public static class CglibAutoProxyConfiguration {
public CglibAutoProxyConfiguration() {
}
} @Configuration
@EnableTransactionManagement(
proxyTargetClass = false
)
@ConditionalOnProperty(
prefix = "spring.aop",
name = {"proxy-target-class"},
havingValue = "false",
matchIfMissing = false
)
public static class JdkDynamicAutoProxyConfiguration {
public JdkDynamicAutoProxyConfiguration() {
}
}
} @Configuration
@ConditionalOnSingleCandidate(PlatformTransactionManager.class)
public static class TransactionTemplateConfiguration {
private final PlatformTransactionManager transactionManager; public TransactionTemplateConfiguration(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
} @Bean
@ConditionalOnMissingBean
public TransactionTemplate transactionTemplate() {
return new TransactionTemplate(this.transactionManager);
}
}
}

我们看到TransactionAutoConfiguration这个自动配置类必须要在DataSourceTransactionManagerAutoConfiguration这个配置类之后才能生效,也就是前面我们已经往Spring容器中注入了DataSourceTransactionManager这个对象才执行这个配置类,然后通过

@EnableTransactionManagement这个注解开启事务,其实和我们自己使用@EnableTransactionManagement是一样的

因此,只要我们在SpringBoot中引入了spring-boot-starter-jdbc这个场景启动器,就会帮我们自动开启事务了,我们只需要使用@Transactional就可以了

mybatis-spring-boot-starter

大多数时候我们在SpringBoot中会引入Mybatis这个orm框架,Mybaits的场景启动器如下

<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>

我们点进去看看

我们看到mybatis-spring-boot-starter这个场景启动器是引入了spring-boot-starter-jdbc这个场景启动器的,因此只要我们在SpringBoot中使用Mybaits,是自动帮我们开启了Spring事务的

总结

springboot 开启事物很简单,只需要加一行注解@Transactional就可以了,前提你用的是jdbctemplate, jpa, Mybatis,这种常见的orm。

SpringBoot 源码解析 (八)----- Spring Boot 精髓:事务源码解析的更多相关文章

  1. Spring Boot入门,源码解析

    目录 1.Spring Boot简介 2.微服务 3.Spring Boot HelloWorld 3.1 创建一个Maven工程 3.2 导入依赖Spring Boot相关的依赖 3.3 编写一个主 ...

  2. Spring Boot 自动配置 源码分析

    Spring Boot 最大的特点(亮点)就是自动配置 AutoConfiguration 下面,先说一下 @EnableAutoConfiguration ,然后再看源代码,到底自动配置是怎么配置的 ...

  3. spring boot 2.0 源码分析(一)

    在学习spring boot 2.0源码之前,我们先利用spring initializr快速地创建一个基本的简单的示例: 1.先从创建示例中的main函数开始读起: package com.exam ...

  4. spring boot 2.0 源码分析(二)

    在上一章学习了spring boot 2.0启动的大概流程以后,今天我们来深挖一下SpringApplication实例变量的run函数. 先把这段run函数的代码贴出来: /** * Run the ...

  5. spring boot 2.0 源码分析(四)

    在上一章的源码分析里,我们知道了spring boot 2.0中的环境是如何区分普通环境和web环境的,以及如何准备运行时环境和应用上下文的,今天我们继续分析一下run函数接下来又做了那些事情.先把r ...

  6. spring boot 2.0 源码分析(三)

    通过上一章的源码分析,我们知道了spring boot里面的listeners到底是什么(META-INF/spring.factories定义的资源的实例),以及它是创建和启动的,今天我们继续深入分 ...

  7. Spring框架之事务源码完全解析

    Spring框架之事务源码完全解析   事务的定义及特性: 事务是并发控制的单元,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位.通过事务将逻辑相关的一组操作绑定在一 ...

  8. SpringBoot零XML配置的Spring Boot Application

    Spring Boot 提供了一种统一的方式来管理应用的配置,允许开发人员使用属性properties文件.YAML 文件.环境变量和命令行参数来定义优先级不同的配置值.零XML配置的Spring B ...

  9. springboot(十九):使用Spring Boot Actuator监控应用

    微服务的特点决定了功能模块的部署是分布式的,大部分功能模块都是运行在不同的机器上,彼此通过服务调用进行交互,前后台的业务流会经过很多个微服务的处理和传递,出现了异常如何快速定位是哪个环节出现了问题? ...

  10. thymeltesys-基于Spring Boot Oauth2的扫码登录框架

    thymeltesys thymelte是一个基于Spring Boot Oauth2的扫码登录框架,使用PostgreSQL存储数据,之后会慢慢支持其他关系型数据库.即使你不使用整个框架,只使用其中 ...

随机推荐

  1. pytest5-使用conftest.py实现多文件共享fixture

    一个测试工程下是可以有多个conftest.py的文件,一般在工程根目录放一个conftest.py起到全局作用.在不同的测试子目录也可以放conftest.py,作用范围只在该层级以及以下目录生效. ...

  2. 7.Linux文件编辑之Vim

    1.VIM基本概述 1.什么是VIM? vi和vim是Linux下的一个文本编辑工具.(可以理解为windows的记事本,或word文档) 2.为什么要使用VIM? 因为Linux系统一切皆为文件,而 ...

  3. The usage of Markdown---代码块

    目录 1. 序言 2. 代码块 3. 引用中的代码 4. 列表中的代码块 更新时间:2019.09.14 1. 序言   在写技术博客的时候,我们常常需要添加一下代码块用来做演示说明,实际上在这篇博客 ...

  4. win7重装系统经验总结报告(2013年6月29日凌晨1:45)

    win7重装系统经验总结报告(2013年6月29日凌晨1:45) 步骤: 1.考虑被重做的电脑是否有重要文件在C盘.有则转移到D盘等非系统盘. 2.看该电脑是2GB内存还是4GB以上内存. 3.准备好 ...

  5. 字符编码 + python2和python3的编码区别(day08整理)

    目录 昨日回顾 二十三.元组内置方法 二十四.散列表 二十五.字典内置方法 二十六.集合内置方法 二十七.深浅拷贝 拷贝 浅拷贝 深拷贝 今日内容 二十八.字符编码 1.文本编辑器存储信息的过程 2. ...

  6. JVM(5) 类加载机制

    虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化.最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 一.类加载的时机 类从被加载到虚拟机内存中开 ...

  7. Mysql数据库(十一)事务与锁机制

    一.事务机制 1.事务的概念 事务是指一组互相依赖的操作单元的集合,用来保证对数据库的正确修改,保持数据的完整性,如果一个事务的某个单元操作失败,将取消本次事务的全部操作. 比如将A账户的资金转入B账 ...

  8. 设置和获取html里面的内容.html

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  9. 第一篇 Flask初识

    一. Python 现阶段三大主流Web框架 Django Tornado Flask 对比 1.Django 主要特点是大而全,集成了很多组件,例如: Models Admin Form 等等, 不 ...

  10. linux centos ubutun svn搭建

    1.卸载SVN 查看自己是否安装了svn svn 上图显示已安装,可用以下命令进行卸载 sudo apt-get remove --purge subversion (–purge 选项表示彻底删除改 ...