who care @Transactional, how @transactional is use
什么是 @Transactional ?
第一个前提是什么是事务?
是由N步数据库操作序列组成的逻辑执行单元,这系列操作要么全执行,要么全放弃执行。
为什么会有要么,要么的结果?
这是由事务的特性决定
ACID
- A:Atomicity : 原子性
- 数据的变化只会有一种结果。
- C:Consistency : 一致性
- 当数据发生变化时,需全部由一种状态,转变为另一种状态。
- I: Isolation : 隔离性
- 事务与事务之间保持隔离,每个事务内部的操作对其他事务不可见,也不会造成影响。
- D:Durability : 持久性
- 事务一旦成功提交,所提交的结果数据将被永久的储存。直到下一次新的事务对其进行操作
@Transactional
@Transactional 是 Spring 框架提供的声明式事务管理方式。在正确配置事务管理器并使用支持事务的数据库的前提下,标注了 @Transactional 的方法或类的数据库操作会被包裹在一个事务中,理论上能够遵守 ACID 属性,但具体效果还依赖于数据库的能力和事务的配置(如隔离级别、回滚规则等)。
这里是源码:
1 | |
这里可以看到 Propagation(传播属性) 默认的是 REQUIRED,也就是多个事务互相调用时,事务如何在这些方法间传播。
这里可以看下 Propagation 这个枚举类的源码:
1 | |
对源码的解释:
PROPAGATION_REQUIRED
- 支持当前事务,如果当前存在事务,则加入该事务。
- 如果当前没有事务,则新建一个事务。
- 场景:适用于大多数需要事务支持的操作。例如,当你有一个方法需要确保所有数据库操作要么全部成功,要么全部失败时,可以使用这个属性。
PROPAGATION_SUPPORTS
- 支持当前事务,如果当前存在事务,则加入该事务。
- 如果当前没有事务,则以非事务方式执行。
- 比如两个实现类串成一个责任链,调用这个责任链的类开启了默认事务,如果外围类发生异常,整个责任链的调用也会回滚。外围类一并回滚,在这里内外属于同一个事务。
- 场景:适用于不需要事务支持但希望在事务中运行的操作。例如,日志记录功能,它可以在事务中运行以确保日志与实际业务操作保持一致,但如果事务不存在,也可以正常执行。一般来说,如果外围类调用失败,内部的日志记录将会停止记录此次操作,但不会影响外围类的其他不在事务内的上下文日志记录
PROPAGATION_MANDATORY
- 支持当前事务,如果当前存在事务,则加入该事务。
- 如果当前没有事务,则抛出异常。
- 场景:适用于必须在一个事务中执行的操作。例如,某些敏感操作,如果事务不存在可能无法保证数据一致性,因此抛出异常是合理的选择。这也是属于责任链的安全机制,如果一个没有事务配置的类调用了需要事务的类,则会触发责任链内的异常抛出
PROPAGATION_REQUIRES_NEW
- 新建事务,如果当前存在事务,则将当前事务挂起。
- 如果当前没有事务,则新建一个事务。
- 场景:适用于需要独立事务的场景,例如,当一个方法需要保证其操作绝对独立于其他操作时,可以使用此属性。例如,处理支付操作,需要确保支付操作在一个独立的事务中完成,不受其他操作的影响。比如各大银行都会有的骚操作:支付流程必须在一个事务中执行!
PROPAGATION_NOT_SUPPORTED
- 以非事务方式执行,如果当前存在事务,则将当前事务挂起。
- 如果当前没有事务,则以非事务方式执行。
- 是指如果存在事务则将这个事务挂起,并使用新的数据库连接。新的数据库连接不使用事务
- 场景:适用于不需要事务支持的操作,但希望在事务存在时暂停它。例如,某些不需要持久化的查询操作,可以在事务中暂停,以提高性能。还是记录日志,日志记录可以多一条和少一条,但不会影响实际业务操作。上级方法抛出异常不会影响日志记录,同样,日志记录抛出异常不会影响上级方法
PROPAGATION_NEVER
- 如果上级方法有事务,则抛出异常。
- 如果调用 Propagation.NEVER 的方法时,当前线程已经有活跃的事务,Spring 会抛出异常(比如 IllegalTransactionStateException)。因此,使用时需要确保调用上下文符合预期。
- 它与 Propagation.NOT_SUPPORTED 类似,但区别在于:NOT_SUPPORTED 会暂停当前事务并以非事务方式运行,而 NEVER 直接拒绝任何事务上下文。
- 场景 适用于明确要求非事务环境的场景(日志记录、监控操作或某些只读操作),通常是为了性能优化、逻辑独立性或特定业务需求。(更主要的是避免事务带来的性能开销,以及业务逻辑要求某个方法必须独立于调用方的事务上下文(比如某些外部系统调用或非事务性操作))如果你需要的是“暂停事务但仍运行”,可以考虑 Propagation.NOT_SUPPORTED;而如果完全拒绝事务,NEVER 是更严格的选择。
PROPAGATION_NESTED
- 如果当前方法有事务,则在嵌套事务内执行。
- 如果当前方法没有事务,则与
PROPAGATION_REQUIRED行为相同。 - 场景:适用于可能需要回滚到某个中间状态的操作。例如,在一个复杂的业务流程中,某些子操作失败时,可能需要回滚到子操作之前的状态,而不是整个事务。
在订单支付操作中, 整个流程默认 Propagation.REQUIRED , 但是在支付过程中,没必要再开启一个新事务,采用了子事务的单独处理回滚,所以这里采用了 Propagation.NESTED 。
1 | |
或者一个老赖资金被冻结的例子:
1 | |
嵌套事务的坑
嵌套事务依赖于底层数据库是否支持 Savepoint。如果数据库不支持(比如 MySQL 的 MyISAM 引擎),Spring 会抛出异常或无法正确工作。建议使用支持保存点的数据库(如 InnoDB)。
这里再看下TransactionDefinition这个常量配置类, 2003年的类,还特么是 interface!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 package org.springframework.transaction;
import org.springframework.lang.Nullable;
/**
* Interface that defines Spring-compliant transaction properties.
* Based on the propagation behavior definitions analogous to EJB CMT attributes.
*
* <p>Note that isolation level and timeout settings will not get applied unless
* an actual new transaction gets started. As only {@link #PROPAGATION_REQUIRED},
* {@link #PROPAGATION_REQUIRES_NEW} and {@link #PROPAGATION_NESTED} can cause
* that, it usually doesn't make sense to specify those settings in other cases.
* Furthermore, be aware that not all transaction managers will support those
* advanced features and thus might throw corresponding exceptions when given
* non-default values.
*
* <p>The {@link #isReadOnly() read-only flag} applies to any transaction context,
* whether backed by an actual resource transaction or operating non-transactionally
* at the resource level. In the latter case, the flag will only apply to managed
* resources within the application, such as a Hibernate {@code Session}.
*/
public interface TransactionDefinition {
/**
* Support a current transaction; create a new one if none exists.
* Analogous to the EJB transaction attribute of the same name.
* <p>This is typically the default setting of a transaction definition,
* and typically defines a transaction synchronization scope.
*/
int PROPAGATION_REQUIRED = 0;
/**
* Support a current transaction; execute non-transactionally if none exists.
* Analogous to the EJB transaction attribute of the same name.
* <p><b>NOTE:</b> For transaction managers with transaction synchronization,
* {@code PROPAGATION_SUPPORTS} is slightly different from no transaction
* at all, as it defines a transaction scope that synchronization might apply to.
* As a consequence, the same resources (a JDBC {@code Connection}, a
* Hibernate {@code Session}, etc) will be shared for the entire specified
* scope. Note that the exact behavior depends on the actual synchronization
* configuration of the transaction manager!
* <p>In general, use {@code PROPAGATION_SUPPORTS} with care! In particular, do
* not rely on {@code PROPAGATION_REQUIRED} or {@code PROPAGATION_REQUIRES_NEW}
* <i>within</i> a {@code PROPAGATION_SUPPORTS} scope (which may lead to
* synchronization conflicts at runtime). If such nesting is unavoidable, make sure
* to configure your transaction manager appropriately (typically switching to
* "synchronization on actual transaction").
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#SYNCHRONIZATION_ON_ACTUAL_TRANSACTION
*/
int PROPAGATION_SUPPORTS = 1;
/**
* Support a current transaction; throw an exception if no current transaction
* exists. Analogous to the EJB transaction attribute of the same name.
* <p>Note that transaction synchronization within a {@code PROPAGATION_MANDATORY}
* scope will always be driven by the surrounding transaction.
*/
int PROPAGATION_MANDATORY = 2;
/**
* Create a new transaction, suspending the current transaction if one exists.
* Analogous to the EJB transaction attribute of the same name.
* <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
* on all transaction managers. This in particular applies to
* {@link org.springframework.transaction.jta.JtaTransactionManager},
* which requires the {@code javax.transaction.TransactionManager} to be
* made available it to it (which is server-specific in standard Java EE).
* <p>A {@code PROPAGATION_REQUIRES_NEW} scope always defines its own
* transaction synchronizations. Existing synchronizations will be suspended
* and resumed appropriately.
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
*/
int PROPAGATION_REQUIRES_NEW = 3;
/**
* Do not support a current transaction; rather always execute non-transactionally.
* Analogous to the EJB transaction attribute of the same name.
* <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
* on all transaction managers. This in particular applies to
* {@link org.springframework.transaction.jta.JtaTransactionManager},
* which requires the {@code javax.transaction.TransactionManager} to be
* made available it to it (which is server-specific in standard Java EE).
* <p>Note that transaction synchronization is <i>not</i> available within a
* {@code PROPAGATION_NOT_SUPPORTED} scope. Existing synchronizations
* will be suspended and resumed appropriately.
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
*/
int PROPAGATION_NOT_SUPPORTED = 4;
/**
* Do not support a current transaction; throw an exception if a current transaction
* exists. Analogous to the EJB transaction attribute of the same name.
* <p>Note that transaction synchronization is <i>not</i> available within a
* {@code PROPAGATION_NEVER} scope.
*/
int PROPAGATION_NEVER = 5;
/**
* Execute within a nested transaction if a current transaction exists,
* behave like {@link #PROPAGATION_REQUIRED} otherwise. There is no
* analogous feature in EJB.
* <p><b>NOTE:</b> Actual creation of a nested transaction will only work on
* specific transaction managers. Out of the box, this only applies to the JDBC
* {@link org.springframework.jdbc.datasource.DataSourceTransactionManager}
* when working on a JDBC 3.0 driver. Some JTA providers might support
* nested transactions as well.
* @see org.springframework.jdbc.datasource.DataSourceTransactionManager
*/
int PROPAGATION_NESTED = 6;
/**
* Use the default isolation level of the underlying datastore.
* All other levels correspond to the JDBC isolation levels.
* @see java.sql.Connection
*/
int ISOLATION_DEFAULT = -1;
/**
* Indicates that dirty reads, non-repeatable reads and phantom reads
* can occur.
* <p>This level allows a row changed by one transaction to be read by another
* transaction before any changes in that row have been committed (a "dirty read").
* If any of the changes are rolled back, the second transaction will have
* retrieved an invalid row.
* @see java.sql.Connection#TRANSACTION_READ_UNCOMMITTED
*/
int ISOLATION_READ_UNCOMMITTED = 1; // same as java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
/**
* Indicates that dirty reads are prevented; non-repeatable reads and
* phantom reads can occur.
* <p>This level only prohibits a transaction from reading a row
* with uncommitted changes in it.
* @see java.sql.Connection#TRANSACTION_READ_COMMITTED
*/
int ISOLATION_READ_COMMITTED = 2; // same as java.sql.Connection.TRANSACTION_READ_COMMITTED;
/**
* Indicates that dirty reads and non-repeatable reads are prevented;
* phantom reads can occur.
* <p>This level prohibits a transaction from reading a row with uncommitted changes
* in it, and it also prohibits the situation where one transaction reads a row,
* a second transaction alters the row, and the first transaction re-reads the row,
* getting different values the second time (a "non-repeatable read").
* @see java.sql.Connection#TRANSACTION_REPEATABLE_READ
*/
int ISOLATION_REPEATABLE_READ = 4; // same as java.sql.Connection.TRANSACTION_REPEATABLE_READ;
/**
* Indicates that dirty reads, non-repeatable reads and phantom reads
* are prevented.
* <p>This level includes the prohibitions in {@link #ISOLATION_REPEATABLE_READ}
* and further prohibits the situation where one transaction reads all rows that
* satisfy a {@code WHERE} condition, a second transaction inserts a row
* that satisfies that {@code WHERE} condition, and the first transaction
* re-reads for the same condition, retrieving the additional "phantom" row
* in the second read.
* @see java.sql.Connection#TRANSACTION_SERIALIZABLE
*/
int ISOLATION_SERIALIZABLE = 8; // same as java.sql.Connection.TRANSACTION_SERIALIZABLE;
/**
* Use the default timeout of the underlying transaction system,
* or none if timeouts are not supported.
*/
int TIMEOUT_DEFAULT = -1;
***********************
}
理论上, TransactionDefinition 这个接口定义了 Spring 事务的属性,包括传播行为、隔离级别、超时等。
Propagation 枚举类定义了 Spring 事务传播行为,包括 REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED 等。
ISOLATION_DEFAULT、ISOLATION_READ_UNCOMMITTED、ISOLATION_READ_COMMITTED、ISOLATION_REPEATABLE_READ、ISOLATION_SERIALIZABLE 这几个常量定义了 Spring 事务的隔离级别。
TIMEOUT_DEFAULT 常量定义了 Spring 事务的超时时间。
这里的枚举类和常量类都是 Spring 事务的基础,可以根据实际情况进行配置。
使用方式
@Transactional 作用在 类 和 public方法 和并不被推荐的 interface ,作用范围顾名思义。其默认配置回滚 RunTimeException 及其子类,也可以直接指定 回滚 Exceptioin 及其子类:@Transactional(rollbackFor = Exception.class)
或者指定事务传播行为:@Transactional(propagation = Propagation.REQUIRED)
或者指定事务隔离级别:@Transactional(isolation = Isolation.SERIALIZABLE)
或者指定事务超时时间:@Transactional(timeout = 30)
或者指定事务传播行为、隔离级别、超时时间,回滚异常类:@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.SERIALIZABLE, timeout = 30,rollbackFor = Exception.class)
事务管理器 (编程式事务管理)
Spring 事务管理器是 Spring 事务的核心,负责事务的提交、回滚、资源的获取和释放等事务管理操作。
Spring 提供了多种事务管理器,包括 DataSourceTransactionManager、HibernateTransactionManager、JpaTransactionManager、JtaTransactionManager 等。
DataSourceTransactionManager 用于管理 JDBC 事务,它会自动获取 JDBC Connection,并对 Connection 进行事务的提交、回滚、关闭等操作。
HibernateTransactionManager 用于管理 Hibernate 事务,它会自动获取 Hibernate Session,并对 Session 进行事务的提交、回滚、关闭等操作。
JpaTransactionManager 用于管理 JPA 事务,它会自动获取 JPA EntityManager,并对 EntityManager 进行事务的提交、回滚、关闭等操作。
Spring 事务管理器的配置如下:
1 | |
声明式事务调用方式
@Transactional 注解失效场景
1.方法调用为内部调用(非代理调用)
pring 的事务管理是基于 AOP(面向切面编程)实现的,默认通过动态代理(JDK 代理或 CGLIB 代理)增强目标类。如果在同一个类中,方法 A 调用方法 B,而 @Transactional 注解在方法 B 上,由于没有经过代理,事务不会生效。
例子:
1 | |
但是我想通过直接在类中进行内部调用如何,该怎样操作呢?
需要在入口类加上 @EnableAspectJAutoProxy
1 | |
或者实现 ApplicationContextAware 接口 ,获取代理类在容器里的Bean
1 | |
以及调用 @Autowired 或者 @Resource 注入 MyService 类。优雅吗?
这里,理论上,一切可以获取Spring 容器中的Bean 都可以进行调用方法!
方法不是 public 的
Spring AOP 只能代理 public 方法。如果 @Transactional 注解标注在非 public 方法上(例如 private 或 protected),事务不会生效。
1 | |
异常被捕获但未抛出
1 | |
事务传播行为不生效
事务传播属性配置不当
原因:@Transactional 的 propagation 属性默认是 Propagation.REQUIRED,表示如果当前存在事务则加入,不存在则新建事务。如果设置为 PROPAGATION_SUPPORTS、PROPAGATION_NOT_SUPPORTED、 PROPAGATION_NEVER,则事务不会生效。
这些单独配置且方法外部上级方法没有配置事务,都会造成方法内的事务不生效。
个别数据库引擎不支持事务
多线程导致事务失效
Spring 的事务是基于 ThreadLocal 实现的,每个线程有独立的事务上下文。如果在方法中开启新线程执行数据库操作,新线程无法继承原线程的事务。
1 | |
CompletableFuture.runAsync 默认使用 ForkJoinPool.commonPool() 执行任务,新线程没有继承主线程的 TransactionManager 的 ThreadLocal 事务上下文,导致事务失效。
Future 通过线程池执行任务时,新线程无法访问主线程的 ThreadLocal 事务状态,因此事务失效。
解决方式
- 使用编程式事务管理这种方式每个异步任务有独立的事务,无法保证整体一致性。如果需要整体回滚,需结合其他机制(如补偿逻辑)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23@Service
public class MyService {
@Autowired
private MyRepository myRepository;
@Autowired
private TransactionTemplate transactionTemplate;
public void myTransactionalMethod() {
transactionTemplate.execute(status -> {
myRepository.save(new Entity("Step 1"));
return null;
});
CompletableFuture.runAsync(() -> {
transactionTemplate.execute(status -> {
myRepository.save(new Entity("Step 2"));
return null;
});
});
}
}
传递事务上下文到新线程
1 | |
通过 TransactionSynchronizationManager 保存主线程的事务状态到子线程中再恢复。
- 尽量避免在事务方法中引入异步操作。
- 如果必须异步,可以使用编程式事务管理或传递事务上下文,但需权衡复杂度和一致性需求。
未启用事务管理器(Spring 需要考虑 ,Spring Boot 自动配置)
原因:如果项目中没有配置 @EnableTransactionManagement 或缺少事务管理器(DataSourceTransactionManager)的 Bean,@Transactional 将不起作用。
解决办法:
在配置类上添加 @EnableTransactionManagement。
确保正确配置数据源和事务管理器:
1 | |
或者 :
1 | |
Spring Boot 自动配置:
1 | |
这里去找 META-INF/spring.factories 文件
嗯,啥都没有
但是在下方有个类似的同名文件: spring-autoconfigure-metadata.properties
看下被谁引用了: AutoConfigurationMetadataLoader
调用方也是 AutoConfigurationImportSelector
1 | |
继续向上追查
1 | |
注意。这里有两个 selectImports 方法,第一个属于 ImportSelector 第二个属于 DeferredImportSelector。
DeferredImportSelector 接口 又继承了 ImportSelector。
DeferredImportSelector 作为 ImportSelector 的延迟实现,在 ApplicationContext 初始化时,会调用 selectImports 方法,而 selectImports 方法又会调用DeferredImportSelector 的 getAutoConfigurationEntry 方法。
DeferredImportSelector 里还有 group 方法,属于是逐步为 ImportSelector 细化解析流程
然后来看下 spring-autoconfigure-metadata.properties 里是如何配置的:
1 | |
直接AI 解释下:
1. org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
这是 Spring Boot 提供的事务管理的自动配置类。它负责在适当的条件下自动配置事务相关的 bean,比如 TransactionManager 和 TransactionTemplate。
ConditionalOnClass=org.springframework.transaction.PlatformTransactionManager
这个注解表示该自动配置类只有在类路径中存在 PlatformTransactionManager(Spring 的事务管理核心接口)时才会生效。这是 Spring Boot 条件配置的典型用法,确保只有在事务管理相关依赖存在时才启用配置。
AutoConfigureAfter=…
表示这个配置类会在指定的其他自动配置类(如 JtaAutoConfiguration, HibernateJpaAutoConfiguration, DataSourceTransactionManagerAutoConfiguration 等)之后执行。这确保事务管理的配置能够依赖于数据库、JPA 或 JTA 的配置完成后再生效。
2. TransactionAutoConfiguration$EnableTransactionManagementConfiguration
这是 TransactionAutoConfiguration 的一个内部配置类,专门处理 @EnableTransactionManagement 相关的配置(比如支持 @Transactional 注解)。
ConditionalOnBean=org.springframework.transaction.TransactionManager
表示这个配置只有在容器中存在 TransactionManager bean 时才会生效。TransactionManager 是事务管理的核心组件,可能由其他配置(如 JDBC、JPA 或 JTA)提供。
3. TransactionAutoConfiguration$TransactionTemplateConfiguration
这是另一个内部配置类,负责配置 TransactionTemplate,它是一个用于编程式事务管理的工具。
ConditionalOnSingleCandidate=org.springframework.transaction.PlatformTransactionManager
表示只有当容器中存在单一候选的 PlatformTransactionManager 时,这个配置才会生效。如果有多个 PlatformTransactionManager bean(比如同时配置了 JPA 和 JDBC 的事务管理器),Spring Boot 不会自动配置 TransactionTemplate,以避免歧义。
4. org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration
这是 JTA(Java Transaction API,分布式事务)的自动配置类,适用于需要分布式事务的场景。它会根据不同的 JTA 实现(比如 Atomikos 或 JNDI)进行配置。
ConditionalOnClass=javax.transaction.Transaction
表示只有在类路径中存在 javax.transaction.Transaction(JTA 的核心接口)时,这个配置才会生效。
AutoConfigureBefore=…
表示这个配置会在一些其他自动配置类(如 XADataSourceAutoConfiguration, HibernateJpaAutoConfiguration 等)之前执行。这是因为 JTA 事务管理需要先于数据源或 ORM 配置完成。
5. org.springframework.boot.autoconfigure.transaction.jta.AtomikosJtaConfiguration
这是 JTA 配置的一个子类,专门为 Atomikos(一个流行的 JTA 事务管理器实现)提供支持。
ConditionalOnClass=com.atomikos.icatch.jta.UserTransactionManager,org.springframework.transaction.jta.JtaTransactionManager
表示只有在类路径中存在 Atomikos 的 UserTransactionManager 和 Spring 的 JtaTransactionManager 时,这个配置才会生效。这是确保 Atomikos 依赖可用。
AtomikosJtaConfiguration$AtomikosJtaJmsConfiguration
这是 Atomikos 配置的子类,专门处理 JMS(Java Message Service)的事务支持。
ConditionalOnClass=javax.jms.Message
表示只有在类路径中存在 JMS 的 Message 类时,这个 JMS 相关配置才会生效。
6. org.springframework.boot.autoconfigure.transaction.jta.JndiJtaConfiguration
这是另一个 JTA 配置子类,用于通过 JNDI(Java Naming and Directory Interface)查找事务管理器,通常在应用服务器(如 WebSphere、WebLogic)中使用。
ConditionalOnClass=org.springframework.transaction.jta.JtaTransactionManager
表示只有在类路径中存在 JtaTransactionManager 时,这个配置才会生效。
总结
这些配置类的作用是:
- 模块化事务支持:Spring Boot 根据类路径中的依赖(如 JDBC、JPA、JTA、Atomikos 等)自动配置事务管理。
- 条件化加载:通过 ConditionalOnClass、ConditionalOnBean 等注解,确保只有在必要依赖存在时才启用相关配置,避免不必要的加载。
- 顺序控制:通过 AutoConfigureAfter 和 AutoConfigureBefore 控制配置的执行顺序,确保依赖关系正确。
- 灵活性:支持不同的使用场景,比如编程式事务(TransactionTemplate)、声明式事务(@Transactional)、分布式事务(JTA)等。