Spring事务部分源码解析(三) - TransactionSynchronization
接下来阅读触发时间相关源码
AbstractPlatformTransactionManager
可以看到触发事件有四个. commit前后,completion前后,
我们看下方代码比较直观
1 |
|
private void processRollback(DefaultTransactionStatus status) {
try {
try {
triggerBeforeCompletion(status);
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug(“Rolling back transaction to savepoint”);
}
status.rollbackToHeldSavepoint();
}
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug(“Initiating transaction rollback”);
}
doRollback(status);
}
else if (status.hasTransaction()) {
if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
if (status.isDebug()) {
logger.debug(“Participating transaction failed - marking existing transaction as rollback-only”);
}
doSetRollbackOnly(status);
}
else {
if (status.isDebug()) {
logger.debug(“Participating transaction failed - letting transaction originator decide on rollback”);
}
}
}
else {
logger.debug(“Should roll back transaction but cannot - no transaction available”);
}
}
catch (RuntimeException ex) {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw ex;
}
catch (Error err) {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw err;
}
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
}
finally {
cleanupAfterCompletion(status);
}
}
1 |
|
到这里,我们的关注点就应该是TransactionSynchronization.至于TransactionSynchronizationUtils,只是通过TransactionSynchronizationManager..getSynchronizations()获取TransactionSynchronization,然后遍历调用而已
1 |
|
我们发现两个类是继承了ResourceHolderSynchronization
1 |
|
@Override
public void suspend() {
if (this.holderActive) {
TransactionSynchronizationManager.unbindResource(this.resourceKey);
}
}
@Override
public void resume() {
if (this.holderActive) {
TransactionSynchronizationManager.bindResource(this.resourceKey, this.resourceHolder);
}
}
@Override
public void flush() {
flushResource(this.resourceHolder);
}
@Override
public void beforeCommit(boolean readOnly) {
}
@Override
public void beforeCompletion() {
if (shouldUnbindAtCompletion()) {
TransactionSynchronizationManager.unbindResource(this.resourceKey);
this.holderActive = false;
if (shouldReleaseBeforeCompletion()) {
releaseResource(this.resourceHolder, this.resourceKey);
}
}
}
@Override
public void afterCommit() {
if (!shouldReleaseBeforeCompletion()) {
processResourceAfterCommit(this.resourceHolder);
}
}
@Override
public void afterCompletion(int status) {
if (shouldUnbindAtCompletion()) {
boolean releaseNecessary = false;
if (this.holderActive) {
// The thread-bound resource holder might not be available anymore,
// since afterCompletion might get called from a different thread.
this.holderActive = false;
TransactionSynchronizationManager.unbindResourceIfPossible(this.resourceKey);
this.resourceHolder.unbound();
releaseNecessary = true;
}
else {
releaseNecessary = shouldReleaseAfterCompletion(this.resourceHolder);
}
if (releaseNecessary) {
releaseResource(this.resourceHolder, this.resourceKey);
}
}
else {
// Probably a pre-bound resource...
cleanupResource(this.resourceHolder, this.resourceKey, (status == STATUS_COMMITTED));
}
this.resourceHolder.reset();
}
/**
* Return whether this holder should be unbound at completion
* (or should rather be left bound to the thread after the transaction).
* <p>The default implementation returns {@code true}.
*/
protected boolean shouldUnbindAtCompletion() {
return true;
}
/**
* Return whether this holder's resource should be released before
* transaction completion ({@code true}) or rather after
* transaction completion ({@code false}).
* <p>Note that resources will only be released when they are
* unbound from the thread ({@link #shouldUnbindAtCompletion()}).
* <p>The default implementation returns {@code true}.
* @see #releaseResource
*/
protected boolean shouldReleaseBeforeCompletion() {
return true;
}
/**
* Return whether this holder's resource should be released after
* transaction completion ({@code true}).
* <p>The default implementation returns {@code !shouldReleaseBeforeCompletion()},
* releasing after completion if no attempt was made before completion.
* @see #releaseResource
*/
protected boolean shouldReleaseAfterCompletion(H resourceHolder) {
return !shouldReleaseBeforeCompletion();
}
/**
* Flush callback for the given resource holder.
* @param resourceHolder the resource holder to flush
*/
protected void flushResource(H resourceHolder) {
}
/**
* After-commit callback for the given resource holder.
* Only called when the resource hasn't been released yet
* ({@link #shouldReleaseBeforeCompletion()}).
* @param resourceHolder the resource holder to process
*/
protected void processResourceAfterCommit(H resourceHolder) {
}
/**
* Release the given resource (after it has been unbound from the thread).
* @param resourceHolder the resource holder to process
* @param resourceKey the key that the ResourceHolder was bound for
*/
protected void releaseResource(H resourceHolder, K resourceKey) {
}
/**
* Perform a cleanup on the given resource (which is left bound to the thread).
* @param resourceHolder the resource holder to process
* @param resourceKey the key that the ResourceHolder was bound for
* @param committed whether the transaction has committed ({@code true})
* or rolled back ({@code false})
*/
protected void cleanupResource(H resourceHolder, K resourceKey, boolean committed) {
}
1 |
|
我们再回头想一下,我们是从TransactionSynchronizationManager才找到TransactionSynchronization.为什么TransactionSynchronization会放在TransactionSynchronizationManager.TransactionSynchronizationManager的意义在于什么?我们看一下
## TransactionSynchronizationManager
![image-20190918221920971](https://image.baidu.com/search/down?url=http://tva1.sinaimg.cn/large/0081Kckwly1gki3r7w4xnj30pw0hvmzl.jpg)
> 方法大致如下
> 注册,解绑,绑定,获取,清空
> 我们看一下属性
![image-20190918222051306](https://raw.githubusercontent.com/Gallrax/blog-image/master/uPic/0081Kckwly1gki3r4ysyyj30lo0ah0uf-20230318170735964.jpg)
> 看到ThreadLocal,似乎知道了些什么
> 多个线程,每个线程又需要对应多个厂商的事务连接,并且每个事务连接朝生夕死,虽然spring容器支持多例,但是多例如何传递?需要怎么处理?
> 通过TransactionSynchronizationManager的ThreadLocal来在线程上下文传递.也许才是最解耦最优雅的方式
## 总结
> AbstractPlatformTransactionManager提供抽象方法,子类具体实现(RabbitTransactionManager, DataSourceTransactionManager)
> TransactionSynchronization提供接口供第三方扩展注册,用于一个事务的多方处理(db, mq等, 实现如RabbitResourceSynchronization, RedisTransactionSynchronizer, SqlSessionSynchronization)
> 那么问题又来了AbstractPlatformTransactionManager的实现类在什么时候注册,是么时候获取?
> TransactionSynchronization的实现类在什么时候注册?什么时候绑定?什么时候获取?
> 写一篇讲解Spring定义抽象的实现类何时加载处理