This is the fifth day of my participation in Gwen Challenge
We all know that Spring’s transactions are implemented by Aop, and that Spring creates a proxy object and then implements the specific logic by invoking the Invoke method via TransactionIntercept. We’ll look at that later
I. Related concepts
Let’s review the well-worn ACID nature of transactions
A: Atomicity: Operations cannot be split, either all succeed or all fail. C: consistency: transactions transfer data from one consistent state to another consistent state I: Isolation: Isolation prevents inconsistencies caused by cross-execution when multiple transactions are executed concurrently. D: Durability: Modifications to data are permanent.
Transaction isolation level:
Read Uncommit: A possible dirty Read, that is, Read data not committed by another transaction is Read commit: a possible problem of Repeatable Read, that is, the results of two reads are inconsistent. Phantom reading can occur and data can be read from other committed transactions after update. (MVCC related, shared later) serializable
Spring transaction apis
- Transaction definition: Contains information such as the isolation level of the transaction and the propagation behavior of the transaction
- Transaction properties: Implements an extension of the rollback rule
TransactionAttribute extends TransactionDefinition
boolean rollbackOn(Throwable ex);
- Transaction manager:
public interface PlatformTransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition definition)throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}
Copy the code
- Transaction runtime status:
public interface TransactionStatus extends SavepointManager.Flushable {
boolean isNewTransaction(a);
boolean hasSavepoint(a);// Rollback to a point
void setRollbackOnly(a);
boolean isRollbackOnly(a);
@Override
void flush(a);
boolean isCompleted(a);
}
Copy the code
- TransactionInterceptor: TransactionInterceptor
- TransactionAspectSupport: TransactionAspectSupport
The inner class TransactionInfo encapsulates the properties of the transaction.
protected final class TransactionInfo {
@Nullable
private final PlatformTransactionManager transactionManager;
@Nullable
private final TransactionAttribute transactionAttribute;
private final String joinpointIdentification;
@Nullable
private TransactionStatus transactionStatus;
@Nullable
private TransactionInfo oldTransactionInfo;
public TransactionInfo(@Nullable PlatformTransactionManager transactionManager,
@Nullable TransactionAttribute transactionAttribute, String joinpointIdentification) {
this.transactionManager = transactionManager;
this.transactionAttribute = transactionAttribute;
this.joinpointIdentification = joinpointIdentification;
}
public PlatformTransactionManager getTransactionManager(a) {
Assert.state(this.transactionManager ! =null."No PlatformTransactionManager set");
return this.transactionManager;
}
@Nullable
public TransactionAttribute getTransactionAttribute(a) {
return this.transactionAttribute;
}
/** * Return a String representation of this joinpoint (usually a Method call) * for use in logging. */
public String getJoinpointIdentification(a) {
return this.joinpointIdentification;
}
public void newTransactionStatus(@Nullable TransactionStatus status) {
this.transactionStatus = status;
}
@Nullable
public TransactionStatus getTransactionStatus(a) {
return this.transactionStatus;
}
/** * Return whether a transaction was created by this aspect, * or whether we just have a placeholder to keep ThreadLocal stack integrity. */
public boolean hasTransaction(a) {
return (this.transactionStatus ! =null);
}
private void bindToThread(a) {
// Expose current TransactionStatus, preserving any existing TransactionStatus
// for restoration after this transaction is complete.
this.oldTransactionInfo = transactionInfoHolder.get();
transactionInfoHolder.set(this);
}
private void restoreThreadLocalStatus(a) {
// Use stack to restore old transaction TransactionInfo.
// Will be null if none was set.
transactionInfoHolder.set(this.oldTransactionInfo);
}
@Override
public String toString(a) {
return (this.transactionAttribute ! =null ? this.transactionAttribute.toString() : "No transaction"); }}Copy the code
TransactionInterceptor, the TransactionInterceptor mentioned above, processes transactions by calling the invokeWithinTransaction method of its parent class TransactionAspectSupport. This method supports both declarative and programmatic transactions.
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.Class<? > targetClass = (invocation.getThis() ! =null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
Copy the code
protected Object invokeWithinTransaction(Method method, @NullableClass<? > targetClass,final InvocationCallback invocation) throws Throwable {
// Query the target method transaction attributes, determine the transaction manager, construct the join point identifier (used to confirm the transaction name)
TransactionAttributeSource tas = getTransactionAttributeSource();
finalTransactionAttribute txAttr = (tas ! =null ? tas.getTransactionAttribute(method, targetClass) : null);
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
// Transaction fetch
TransactionInfotxInfo=createTransactionIfNecessary(tm,txAttr,joinpointIdentification);
Object retVal;
try {
// Execute the target method via a callback
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// The target method throws an exception and performs a transaction commit or rollback depending on the exception type
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
// Clear the current thread transaction information
cleanupTransactionInfo(txInfo);
}
// The target method executed successfully and committed the transaction
commitTransactionAfterReturning(txInfo);
return retVal;
}
Copy the code
Above, thanks for reading.