Next, let's analyze the processing of connection resources by transaction operations, that is, the management of resources (resources attribute) by transaction synchronization manager in transaction processing.
2. Spring transaction processing
The TransactionSynchronizationManager#bindResource binding connects resources to the resources attribute in TransactionSynchronizationManager. The following is the binding sequence diagram:
TransactionInterceptor is Spring's proxy entry for transaction method processing, which abstracts JDBC transactions:
// Get connection Connection conn = DataSource.getConnection(); // Set auto submit false conn..setAutoCommit(false); try { // Business operation doSomething(); } catch (Exception e) { // Rollback transaction conn.rollback(); } // Commit transaction conn.commit();
TransactionAspectSupport#invokeWithinTransaction
TransactionAspectSupport#invokeWithinTransaction is the processing of Spring. Let's briefly analyze its processing process:
The logic of the above code is as follows:
-
TransactionAttributeSource#getTransactionAttribute obtains transaction related information (TransactionAttribute). Take annotated transactions as an example to see if there is @ Transactional annotation on the method acquisition class.
-
Get the platform transaction manager configured in the Spring container, and then the real transaction processing
-
Create transaction information (TransactionInfo), which contains transaction manager (platform transaction manager) and transaction related information (TransactionAttribute)
-
This is followed by Spring's abstract operations on transactions, including setting auto commit false, business operations, abnormal rollback transactions and normal commit transactions
Let's get back to the point. Spring binds the database connection to the ThreadLocal variable through the transaction synchronization manager #bindresource by creating the transaction info. Then, other database operations marked into a transaction can obtain the connection through the transaction synchronization manager #getresource.
Database transactions are connection based, and Spring's transaction implementation for multiple database operations is based on ThreadLocal. Therefore, multithreading cannot be used in transaction operations
3. Extension of Spring transactions – TransactionSynchronization
In the TransactionSynchronizationManager class above, we know that its current thread also saves the TransactionSynchronization object during transaction operation. Along with Spring, this object will have corresponding extensions for each life cycle of transaction processing.
TransactionSynchronization.java
public interface TransactionSynchronization extends Flushable { /** Transaction commit status */ int STATUS_COMMITTED = 0; /** Transaction rollback status */ int STATUS_ROLLED_BACK = 1; /**System abnormal state */ int STATUS_UNKNOWN = 2; void suspend(); void resume(); void flush(); // Before transaction commit void beforeCommit(boolean readOnly); // Before the transaction succeeds or the transaction is rolled back void beforeCompletion(); // After the transaction is successfully committed void afterCommit(); // After the operation is completed (including transaction success or transaction rollback) void afterCompletion(int status); }
The application scenario in the transaction extension project of transaction is to send a message to MQ after the order is successful. Because the transaction is bound to the database connection, if you put the sending message and database operation in one transaction. When sending messages for too long, it will occupy the database connection, so it is necessary to decouple the database operation from sending messages to MQ. You can use the method of TransactionSynchronization#afterCommit to send messages to MQ when the data is successfully saved to the database and the transaction is committed.
@Transactional public void finishOrder(Order order){ // Order modified successfully updateOrderSuccess(order); // Send message to MQ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter(){ @Override public void afterCommit() { mqService.send(order); } }); }
After the transaction is successfully committed, the message will be sent to MQ without occupying database connection resources.
4. Spring transaction extension – @ TransactionalEventListener
After Spring framework 4.2, @ TransactionalEventListener can also be used to process database transactions. After successful submission, operations can be performed. This approach is more elegant than transaction synchronization. It is used as follows:
@Transactional public void finishOrder(Order order){ // Order modified successfully updateOrderSuccess(order); // Publishing Spring Event events applicationEventPublisher.publishEvent(new MyAfterTransactionEvent(order)); } @Slf4j @Component private static class MyTransactionListener { @Autowired private MqService mqService; @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) private void onHelloEvent(MyAfterTransactionEvent event) { Order order = event.getOrder(); mqService.send(order); } } // Define an event, inherited from ApplicationEvent private static class MyAfterTransactionEvent extends ApplicationEvent { private Order order; public MyAfterTransactionEvent(Object source, Order order) { super(source); this.order = order; } public Order getOrder() { return order; } }
Its implementation principle is that when the method of Spring Bean is marked with the ApplicationListenerMethodTransactionalAdapter created through TransactionalEventListenerFactory#createApplicationListener, then the implementation class TransactionSynchronizationEventAdapter of TransactionSynchronization is created in the event callback. And register the TransactionSynchronizationEventAdapter to the current thread through TransactionSynchronizationManager.registerSynchronization.
n implementation class TransactionSynchronizationEventAdapter. And register the TransactionSynchronizationEventAdapter to the current thread through TransactionSynchronizationManager.registerSynchronization.