本篇來講一下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。