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

*爱你&永不变心* 提交于 2019-11-25 17:00:27

本篇来讲一下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。

日常求赞

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

如果这个文章写得还不错,觉得学到了一点东西的话 求点赞👍 对我来说真的 非常有用!!!

创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!