欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringBoot 源码解析 (八)----- Spring Boot 精髓:事务源码解析

程序员文章站 2022-03-20 15:51:14
本篇来讲一下SpringBoot是怎么自动开启事务的,我们先来回顾一下以前SSM中是如何使用事务的 SSM使用事务 导入JDBC依赖包 众所周知,凡是需要跟数据库打交道的,基本上都要添加jdbc的依赖,在Spring项目中,加入的是spring-jdbc依赖:

本篇来讲一下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的场景启动器,我们点进去看看

SpringBoot 源码解析 (八)----- Spring Boot 精髓:事务源码解析

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

datasourcetransactionmanagerautoconfiguration

SpringBoot 源码解析 (八)----- Spring Boot 精髓:事务源码解析

我们看到在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

SpringBoot 源码解析 (八)----- Spring Boot 精髓:事务源码解析

我们看到在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>

我们点进去看看

SpringBoot 源码解析 (八)----- Spring Boot 精髓:事务源码解析

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

总结

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

日常求赞

好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是人才。

如果这个文章写得还不错,觉得学到了一点东西的话 求点赞