Spring Transaction Source Code
Spring provides a unified transaction abstraction layer that decouples underlying transaction implementations—such as JDBC, JPA, Hibernate, and JTA—while offering both declarative (AOP-based) and programmatic management styles. The core philosophy centers around three primary components:
- PlatformTransactionManager handles transaction initiation, commitment, and rollback.
- TransactionDefinition outlines transaction attributes including propagation behavior, isolation levels, and timeouts.
- TransactionStatus monitors the runtime state of an active transaction.
At runtime, Spring selects the appropriate PlatformTransactionManager implementation based on your configuration, seamlessly managing disparate resource types under a single unified architecture.
| Interface | Primary Role | Key Methods |
|---|---|---|
PlatformTransactionManager |
Transaction gateway; manages the transaction lifecycle | getTransaction(TransactionDefinition), commit(TransactionStatus), rollback(TransactionStatus) |
TransactionDefinition |
Defines transaction attributes | getPropagationBehavior(), getIsolationLevel(), getTimeout(), isReadOnly() |
TransactionStatus |
Tracks runtime transaction states | isNewTransaction(), hasSavepoint(), isCompleted() |
Customizing Transaction Attributes Programmatically
TransactionDefinition def = new DefaultTransactionDefinition();
((DefaultTransactionDefinition) def).setPropagationBehavior(
TransactionDefinition.PROPAGATION_REQUIRED);
((DefaultTransactionDefinition) def).setIsolationLevel(
TransactionDefinition.ISOLATION_READ_COMMITTED);
Common Transaction Manager Implementations
| Implementation Class | Target Scenario | Key Source Code Location |
|---|---|---|
DataSourceTransactionManager |
Pure JDBC environments | org.springframework.jdbc.datasource.DataSourceTransactionManager |
JpaTransactionManager |
JPA (EntityManager) environments |
org.springframework.orm.jpa.JpaTransactionManager |
HibernateTransactionManager |
Native Hibernate (Session) environments |
org.springframework.orm.hibernate5.HibernateTransactionManager |
JtaTransactionManager |
Distributed transactions (JTA) | org.springframework.transaction.jta.JtaTransactionManager |
Core Workflow of DataSourceTransactionManager
public TransactionStatus getTransaction(TransactionDefinition definition) {
// 1. Acquire current connection (reuse if already bound to the thread)
Connection con = DataSourceUtils.getConnection(this.dataSource);
// 2. Configure auto-commit based on transaction attributes
boolean previousAutoCommit = con.getAutoCommit();
con.setAutoCommit(false);
// 3. Create and return a DefaultTransactionStatus instance
return new DefaultTransactionStatus(con, true, false,
definition.isReadOnly(), false, null);
}
- Connection Acquisition: Utilizing
DataSourceUtils.getConnectionensures that database connections are safely reused across the same transactional synchronization context. - Auto-Commit Configuration: Disabling auto-commit allows subsequent explicit
commitorrollbackoperations to take effect. - State Object Return: The
DefaultTransactionStatusencapsulates connection details, flags for new transactions, and read-only statuses.
Key Implementation in JpaTransactionManager
protected EntityManagerHolder doBegin(Object transaction, TransactionDefinition definition) {
EntityManagerFactory emf = this.entityManagerFactory;
EntityManager em = emf.createEntityManager();
// Bind the EntityManager holder to the current thread
TransactionSynchronizationManager.bindResource(emf, new EntityManagerHolder(em));
// Initiate the native JPA transaction
em.getTransaction().begin();
return new EntityManagerHolder(em);
}
- An
EntityManageris created and registered with theTransactionSynchronizationManager, ensuring that all DAO operations within the same transaction share an identical persistence context. - It triggers the native JPA transaction via
em.getTransaction().begin()to officially start the unit of work.
Implementation Mechanism of Declarative Transactions
TransactionInterceptor
The TransactionInterceptor acts as a Spring AOP MethodInterceptor, weaving transactional behavior around target methods during execution.
public Object invoke(MethodInvocation invocation) throws Throwable {
// 1. Resolve transaction attributes matching the invoked method
TransactionAttribute txAttr = this.attributeSource.getTransactionAttribute(
invocation.getMethod(), invocation.getThis().getClass());
// 2. Proceed directly if no transaction attribute is found
if (txAttr == null) {
return invocation.proceed();
}
// 3. Initialize transaction info and retrieve the transaction status
TransactionInfo txInfo = createTransactionIfNecessary(txAttr, methodName);
try {
// 4. Execute the underlying business logic
Object retVal = invocation.proceed();
// 5. Commit the transaction upon successful completion
commitTransactionAfterReturning(txInfo);
return retVal;
} catch (Throwable ex) {
// 6. Roll back the transaction when an exception is thrown
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
} finally {
// 7. Clean up transaction resources and unbind contexts
cleanupTransactionInfo(txInfo);
}
}
Sources of Transaction Attributes
- XML configuration: Elements like
<tx:advice>and<tx:method>. - Annotations:
@Transactional(parsed viaAnnotationTransactionAttributeSource). - Java Configuration:
@EnableTransactionManagementcombined with@Beandefinitions.
Transaction Synchronization
Spring triggers TransactionSynchronization callbacks before and after transaction commits or rollbacks. These hooks enable deferred resource cleanup, cache flushing, and other lifecycle-dependent tasks.
public interface TransactionSynchronization {
void beforeCommit(boolean readOnly);
void afterCommit();
void beforeCompletion();
void afterCompletion(int status);
}
Common implementations include:
DataSourceTransactionManagerregistering aConnectionHolderto release JDBC connections inside theafterCompletionphase.JpaTransactionManagercleaning up and closing the activeEntityManagerwithinafterCompletion.
Enabling Transaction Management
XML-Based Configuration
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
Java-Based Configuration
@Configuration
@EnableTransactionManagement
public class TxConfig {
@Bean
public DataSource dataSource() {
return DataSourceBuilder.create()
.url("jdbc:h2:mem:test")
.username("sa")
.build();
}
@Bean
public PlatformTransactionManager txManager(DataSource ds) {
return new DataSourceTransactionManager(ds);
}
}
@EnableTransactionManagementautomatically registers theTransactionInterceptorandBeanFactoryTransactionAttributeSourceAdvisorto weave AOP proxies into your application context.
Practical Example: Declarative Transaction Flow
@Service
public class OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private StockDao stockDao;
@Transactional(propagation = Propagation.REQUIRED,
isolation = Isolation.READ_COMMITTED,
timeout = 30,
rollbackFor = Exception.class)
public void createOrder(Order order) {
orderDao.insert(order); // Insert record into order table
stockDao.decrease(order.getSkuId(), order.getQty()); // Deduct inventory
// Triggers a rollback if a RuntimeException occurs due to insufficient stock
}
}
- Propagation:
REQUIREDjoins an existing transaction if present; otherwise, it creates a new one. - Isolation:
READ_COMMITTEDprevents dirty reads. - Timeout: Automatically rolls back if execution exceeds 30 seconds.
- Rollback Rules: Any instance of
Exceptionor its subclasses triggers a rollback.
Tips for Debugging Transaction Source Code
- Enable DEBUG Logging:
logging.level.org.springframework.transaction=DEBUG logging.level.org.springframework.jdbc.datasource=DEBUG - Use
TransactionSynchronizationManager.isActualTransactionActive()to check whether the current thread is operating inside an active transaction. - Inspect
TransactionInfo(an internal helper class withinTransactionInterceptor) to examine active transaction attributes, statuses, and synchronization callbacks. - Set IDE Breakpoints inside
DataSourceTransactionManager.doBegin,commit, androllbackto observe real-time modifications to connection auto-commit states.
Summary
The Spring transaction framework uses a unified abstraction combined with multiple implementations design, allowing developers to switch between different persistence technologies effortlessly. The core execution pipeline can be summarized as follows:
- Resolve transaction attributes via
TransactionAttributeSource. - Obtain or create a transaction using
PlatformTransactionManager.getTransaction. - Execute business logic intercepted by the
TransactionInterceptorAOP aspect. - Commit or roll back based on the execution outcome (
commit/rollback). - Synchronize resource cleanup through
TransactionSynchronization.
Mastering these implementation details empowers you to handle advanced transaction control, performance tuning, and troubleshooting effectively in real-world enterprise applications.