SpringBoot 源码解析 (八)----- Spring Boot 精髓:事务源码解析
本篇来讲一下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,我们进去看看
1 @configuration 2 //在类路径下有这个类存在platformtransactionmanager时,这个配置类才会生效 3 //而前面我们已经引入了spring-boot-starter-jdbc,那自然是存在了 4 @conditionalonclass({ jdbctemplate.class, platformtransactionmanager.class }) 5 @autoconfigureorder(ordered.lowest_precedence) 6 @enableconfigurationproperties(datasourceproperties.class) 7 public class datasourcetransactionmanagerautoconfiguration { 8 9 @configuration 10 @conditionalonsinglecandidate(datasource.class) 11 static class datasourcetransactionmanagerconfiguration { 12 13 private final datasource datasource; 14 15 private final transactionmanagercustomizers transactionmanagercustomizers; 16 17 datasourcetransactionmanagerconfiguration(datasource datasource, 18 objectprovider<transactionmanagercustomizers> transactionmanagercustomizers) { 19 this.datasource = datasource; 20 this.transactionmanagercustomizers = transactionmanagercustomizers 21 .getifavailable(); 22 } 23 24 @bean 25 //没有当spring容器中不存在platformtransactionmanager这个对象时,创建datasourcetransactionmanager 26 //也就是如果我们自定义了datasourcetransactionmanager并注入spring容器,这里将不会执行 27 @conditionalonmissingbean(platformtransactionmanager.class) 28 public datasourcetransactionmanager transactionmanager(datasourceproperties properties) { 29 //创建datasourcetransactionmanager注入spring容器,并且把datasource传进去 30 datasourcetransactionmanager transactionmanager = new datasourcetransactionmanager(this.datasource); 31 if (this.transactionmanagercustomizers != null) { 32 this.transactionmanagercustomizers.customize(transactionmanager); 33 } 34 return transactionmanager; 35 } 36 37 } 38 39 }
很明显只要我们导入了spring-boot-starter-jdbc场景启动器,并且我们没有自定义datasourcetransactionmanager,那么事务管理器自动配置类datasourcetransactionmanagerautoconfiguration会自动为我们创建datasourcetransactionmanager并注入spring容器中。但是这还不够,我们前面还是需要通过@enabletransactionmanagement开启事务呢,如果不开启事务,@transactional是不起任何作用的。下面我们就来看看是如何开启事务的
transactionautoconfiguration
我们看到在spring.factories中配置了事务自动开启配置类transactionautoconfiguration,我们进去看看
1 @configuration 2 //和datasourcetransactionmanagerautoconfiguration中是一样的 3 //引入了spring-boot-starter-jdbc,那自然是存在了platformtransactionmanager 4 @conditionalonclass({platformtransactionmanager.class}) 5 //这个自动配置类必须要在datasourcetransactionmanagerautoconfiguration这个自动配置类之后才能生效 6 //也就是前面我们已经往spring容器中注入了datasourcetransactionmanager这个对象才执行这个配置类 7 @autoconfigureafter({jtaautoconfiguration.class, hibernatejpaautoconfiguration.class, datasourcetransactionmanagerautoconfiguration.class, neo4jdataautoconfiguration.class}) 8 @enableconfigurationproperties({transactionproperties.class}) 9 public class transactionautoconfiguration { 10 public transactionautoconfiguration() { 11 } 12 13 @configuration 14 @conditionalonbean({platformtransactionmanager.class}) 15 @conditionalonmissingbean({abstracttransactionmanagementconfiguration.class}) 16 public static class enabletransactionmanagementconfiguration { 17 public enabletransactionmanagementconfiguration() { 18 } 19 20 @configuration 21 //重点:通过 @enabletransactionmanagement注解开启事务 22 //可以看到和我们自己使用@enabletransactionmanagement是一样的 23 @enabletransactionmanagement( 24 proxytargetclass = true 25 ) 26 @conditionalonproperty( 27 prefix = "spring.aop", 28 name = {"proxy-target-class"}, 29 havingvalue = "true", 30 matchifmissing = true 31 ) 32 public static class cglibautoproxyconfiguration { 33 public cglibautoproxyconfiguration() { 34 } 35 } 36 37 @configuration 38 @enabletransactionmanagement( 39 proxytargetclass = false 40 ) 41 @conditionalonproperty( 42 prefix = "spring.aop", 43 name = {"proxy-target-class"}, 44 havingvalue = "false", 45 matchifmissing = false 46 ) 47 public static class jdkdynamicautoproxyconfiguration { 48 public jdkdynamicautoproxyconfiguration() { 49 } 50 } 51 } 52 53 @configuration 54 @conditionalonsinglecandidate(platformtransactionmanager.class) 55 public static class transactiontemplateconfiguration { 56 private final platformtransactionmanager transactionmanager; 57 58 public transactiontemplateconfiguration(platformtransactionmanager transactionmanager) { 59 this.transactionmanager = transactionmanager; 60 } 61 62 @bean 63 @conditionalonmissingbean 64 public transactiontemplate transactiontemplate() { 65 return new transactiontemplate(this.transactionmanager); 66 } 67 } 68 }
我们看到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。
日常求赞
好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是人才。
如果这个文章写得还不错,觉得学到了一点东西的话 求点赞
推荐阅读
-
【spring-boot 源码解析】spring-boot 依赖管理
-
【spring-boot 源码解析】spring-boot 依赖管理梳理图
-
spring5 源码深度解析----- 事务的回滚和提交(100%理解事务)
-
SpringBoot 源码解析 (七)----- Spring Boot的核心能力 - SpringBoot如何实现SpringMvc的?
-
SpringBoot 源码解析 (六)----- Spring Boot的核心能力 - 内置Servlet容器源码分析(Tomcat)
-
Mybaits 源码解析 (十二)----- Mybatis的事务如何被Spring管理?Mybatis和Spring事务中用的Connection是同一个吗?
-
SpringBoot 源码解析 (十)----- Spring Boot 精髓:集成AOP
-
SpringBoot 源码解析 (三)----- Spring Boot 精髓:启动时初始化数据
-
【源码解析】凭什么?spring boot 一个 jar 就能开发 web 项目
-
【spring-boot 源码解析】spring-boot 依赖管理