TransactionAspectSupport.TransactionInfo:内部类 事务Info
它是TransactionAspectSupport
的一个protected
内部类。我觉得有必要先讲解下它:
protected final class TransactionInfo { // 当前事务 的事务管理器 @Nullable private final PlatformTransactionManager transactionManager; // 当前事务 的事务属性 @Nullable private final TransactionAttribute transactionAttribute; // joinpoint标识 private final String joinpointIdentification; // 当前事务 的TransactionStatus @Nullable private TransactionStatus transactionStatus; // 重点就是这个oldTransactionInfo字段 // 这个字段保存了当前事务所在的`父事务`上下文的引用,构成了一个链,准确的说是一个有向无环图 @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() { Assert.state(this.transactionManager != null, "No PlatformTransactionManager set"); return this.transactionManager; } // 注意这个方法名,新的一个事务status public void newTransactionStatus(@Nullable TransactionStatus status) { this.transactionStatus = status; } public boolean hasTransaction() { return (this.transactionStatus != null); } //绑定当前正在处理的事务的所有信息到ThreadLocal private void bindToThread() { // Expose current TransactionStatus // 老的事务 先从线程中拿出来,再把新的(也就是当前)绑定进去~~~~~~ this.oldTransactionInfo = transactionInfoHolder.get(); transactionInfoHolder.set(this); } // 当前事务处理完之后,恢复父事务上下文 private void restoreThreadLocalStatus() { transactionInfoHolder.set(this.oldTransactionInfo); } @Override public String toString() { return (this.transactionAttribute != null ? this.transactionAttribute.toString() : "No transaction"); } }
了解了这个Info内部类之后,接下来可议看看TransactionAspectSupport#createTransactionIfNecessary方法:它是创建事务的一个重要方法。
它会判断是否存在事务,根据事务的传播属性。做出不同的处理,也是做了一层包装,核心是通过TransactionStatus来判断事务的属性
创建事务:createTransactionIfNecessary()
// 若有需要 创建一个TransactionInfo (具体的事务从事务管理器里面getTransaction()出来~) protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr, final String joinpointIdentification) { // If no name specified, apply method identification as transaction name. // 这个简单的说,就是给Name赋值~~~~~ if (txAttr != null && txAttr.getName() == null) { txAttr = new DelegatingTransactionAttribute(txAttr) { @Override public String getName() { return joinpointIdentification; } }; } // 从事务管理器里,通过txAttr拿出来一个TransactionStatus TransactionStatus status = null; if (txAttr != null) { if (tm != null) { status = tm.getTransaction(txAttr); } ... } // 通过TransactionStatus 等,转换成一个通用的TransactionInfo return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); }
准备事务:prepareTransactionInfo()
protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr, String joinpointIdentification, @Nullable TransactionStatus status) { // 构造一个TransactionInfo TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification); if (txAttr != null) { // 如果已存在不兼容的Tx,事务管理器将标记错误 txInfo.newTransactionStatus(status); } ,.. // We always bind the TransactionInfo to the thread, even if we didn't create // a new transaction here. This guarantees that the TransactionInfo stack // will be managed correctly even if no transaction was created by this aspect. // 这句话是最重要的:把生成的TransactionInfo并绑定到当前线程的ThreadLocal txInfo.bindToThread(); return txInfo; }
提交事务:commitTransactionAfterReturning()
//比较简单 只用用事务管理器提交事务即可~~~ 具体的实现逻辑在事务管理器的commit实现里~~~ protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) { if (txInfo != null && txInfo.getTransactionStatus() != null) { txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); } }
回滚事务:completeTransactionAfterThrowing()
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) { if (txInfo != null && txInfo.getTransactionStatus() != null) { // 如果有事务属性了,那就调用rollbackOn看看这个异常需不需要回滚 if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) { try { txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus()); } ... } // 编程式事务没有事务属性,那就commit吧 else { try { txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); } ... } } }
清除(解绑)事务:cleanupTransactionInfo()
protected void cleanupTransactionInfo(@Nullable TransactionInfo txInfo) { if (txInfo != null) { txInfo.restoreThreadLocalStatus(); } }
PlatformTransactionManager:事务管理器
记下硕说另外一大块内容:事务管理器。谈到事务,肯定是离不开它的。
关于事务管理器,不管是JPA(JpaTransactionManager )还是JDBC(DataSourceTransactionManager)甚至是JTA(JtaTransactionManager)等都实现自接口 PlatformTransactionManager
它只提供三个方法:
public interface PlatformTransactionManager { TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException; void commit(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException; }
这三个方法就不用再多说。
下面以最常用的实现:DataSourceTransactionManager 做源码分析~~~
先看看它的抽象实现:AbstractPlatformTransactionManager,这个抽象类提供了处理的模版(其实Spring的设计模式中,很多抽象类都提供了实现模版),然后提供开口给子类去各自实现~
AbstractPlatformTransactionManager
可见它是对PlatformTransactionManager的一个抽象实现。实现Spring的标准事务工作流
这个基类提供了以下工作流程处理:
- 确定如果有现有的事务;
- 应用适当的传播行为;
- 如果有必要暂停和恢复事务;
- 提交时检查rollback-only标记;
- 应用适当的修改当回滚(实际回滚或设置rollback-only);
- 触发同步回调注册(如果事务同步是激活的)
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable { //始终激活事务同步(请参阅事务的传播属性~) public static final int SYNCHRONIZATION_ALWAYS = 0; //仅对实际事务(即,不针对由传播导致的空事务)激活事务同步\不支持现有后端事务 public static final int SYNCHRONIZATION_ON_ACTUAL_TRANSACTION = 1; //永远不激活事务同步 public static final int SYNCHRONIZATION_NEVER = 2; // 相当于把本类的所有的public static final的变量都收集到此处~~~~ private static final Constants constants = new Constants(AbstractPlatformTransactionManager.class); // ===========默认值 private int transactionSynchronization = SYNCHRONIZATION_ALWAYS; // 事务默认的超时时间 为-1表示不超时 private int defaultTimeout = TransactionDefinition.TIMEOUT_DEFAULT; //Set whether nested transactions are allowed. Default is "false". private boolean nestedTransactionAllowed = false; // Set whether existing transactions should be validated before participating(参与、加入) private boolean validateExistingTransaction = false; //设置是否仅在参与事务`失败后`将 现有事务`全局`标记为回滚 默认值是true 需要注意~~~ // 表示只要你的事务失败了,就标记此事务为rollback-only 表示它只能给与回滚 而不能再commit或者正常结束了 // 这个调用者经常会犯的一个错误就是:上层事务service抛出异常了,自己把它给try住,并且并且还不throw,那就肯定会报错的: // 报错信息:Transaction rolled back because it has been marked as rollback-only // 当然喽,这个属性强制不建议设置为false~~~~~~ private boolean globalRollbackOnParticipationFailure = true; // 如果事务被全局标记为仅回滚,则设置是否及早失败~~~~ private boolean failEarlyOnGlobalRollbackOnly = false; // 设置在@code docommit调用失败时是否应执行@code dorollback 通常不需要,因此应避免 private boolean rollbackOnCommitFailure = false; // 此处我们直接可以通过属性们来社会,语意思更清晰些了 // 我们发现使用起来有点枚举的意思了,特别是用XML配置的时候 非常像枚举的使用~~~~~~~ // 这也是Constants的重要意义~~~~ public final void setTransactionSynchronizationName(String constantName) { setTransactionSynchronization(constants.asNumber(constantName).intValue()); } public final void setTransactionSynchronization(int transactionSynchronization) { this.transactionSynchronization = transactionSynchronization; } //... 省略上面所有字段的一些get/set方法~~~ // 最为重要的一个方法,根据实物定义,获取到一个事务TransactionStatus @Override public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException { //doGetTransaction()方法是抽象方法,具体的实现由具体的事务处理器提供(下面会以DataSourceTransactionManager为例子) Object transaction = doGetTransaction(); //如果没有配置事务属性,则使用默认的事务属性 if (definition == null) { definition = new DefaultTransactionDefinition(); } //检查当前线程是否存在事务 isExistingTransaction此方法默认返回false 但子类都复写了此方法 if (isExistingTransaction(transaction)) { // handleExistingTransaction方法为处理已经存在事务的情况 // 这个方法的实现也很复杂,总之还是对一些传播属性进行解析,各种情况的考虑~~~~~ 如果有新事务产生 doBegin()就会被调用~~~~ return handleExistingTransaction(definition, transaction, debugEnabled); } // 超时时间的简单校验~~~~ if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout()); } // 处理事务属性中配置的事务传播特性============== // PROPAGATION_MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException("No existing transaction found for transaction marked with propagation 'mandatory'"); } //如果事务传播特性为required、required_new或nested else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { // 挂起,但是doSuspend()由子类去实现~~~ // 挂起操作,触发相关的挂起注册的事件,把当前线程事物的所有属性都封装好,放到一个SuspendedResourcesHolder // 然后清空清空一下`当前线程事务` SuspendedResourcesHolder suspendedResources = suspend(null); // 此处,开始创建事务~~~~~ try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); // //创建一个新的事务状态 就是new DefaultTransactionStatus() 把个属性都赋值上 DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); // 开始事务,抽象方法,由子类去实现~ doBegin(transaction, definition); //初始化和同步事务状态 是TransactionSynchronizationManager这个类 它内部维护了很多的ThreadLocal prepareSynchronization(status, definition); return status; } catch (RuntimeException | Error ex) { //重新开始 doResume由子类去实现 resume(null, suspendedResources); throw ex; } } // 走到这里 传播属性就是不需要事务的 那就直接创建一个 else { boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); // 这个方法相当于先newTransactionStatus,再prepareSynchronization这两步~~~ // 显然和上面的区别是:中间不回插入调用doBegin()方法,因为没有事务 begin个啥~~ return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null); } } // 再看看commit方法 @Override public final void commit(TransactionStatus status) throws TransactionException { //如果是一个已经完成的事物,不可重复提交 if (status.isCompleted()) { throw new IllegalTransactionStateException("Transaction is already completed - do not call commit or rollback more than once per transaction"); } DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status; // 如果已经标记为了需要回滚,那就执行回滚吧 if (defStatus.isLocalRollbackOnly()) { processRollback(defStatus, false); return; } // shouldCommitOnGlobalRollbackOnly这个默认值是false,目前只有JTA事务复写成true了 // isGlobalRollbackOnly:是否标记为了全局的RollbackOnly if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) { processRollback(defStatus, true); return; } // 提交事务 这里面还是挺复杂的,会考虑到还原点、新事务、事务是否是rollback-only之类的~~ processCommit(defStatus); } // rollback方法 里面doRollback方法交给子类去实现~~~ @Override public final void rollback(TransactionStatus status) throws TransactionException { DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status; processRollback(defStatus, false); } }
从这个抽象类源码分析可以看出,它绝对是一个非常非常典型的模版实现,各个方法实现都是这样。自己先提供实现模版,很多具体的实现方案都开放给子类,比如begin,suspend, resume, commit, rollback等,相当于留好了众多的连接点
这个类的抽象程度非常的高,逻辑也非常的复杂。要想绝对的理解到位,必须要对JDBC的事务非常了解,而且还对这些代码逻辑必须进行精读。书读百遍,其义自见