spring事务多重要,这个真的是很绝,本来我不准备写,结果看到些资料,不写感觉对不起自己个儿,所以这篇来了! 直接上个干货;
spring事务
基于数据库事务和AOP机制
@Transaction注解,创建代理,调用代理方法判断是否加了注解
加了 事务管理器 创建数据库连接,修改autocommit=false,执行sql
传播机制基于数据库连接,这句话很重要!一个数据库连接一个事务
流程图
事务同步器TransactionSynchronization
这个很重要,嘎嘎重要,虽然凭良心说本身呢没做什么事,extends Flushable
这个同步器有个配置transactionSynchronization:
public static final int SYNCHRONIZATION_ALWAYS = 0;//默认,同步始终生效
public static final int SYNCHRONIZATION_ON_ACTUAL_TRANSACTION = 1;//事务同步仅在非 空 事务的时候生效
public static final int SYNCHRONIZATION_NEVER = 2;//从不生效
空事务:
PROPAGATION_SUPPORTS,PROPAGATION_NOT_SUPPORTED,PROPAGATION_NEVER事务传播级别 不处于事务中,无所谓commit和rollback
public interface TransactionSynchronization extends Flushable {
//描述事务当前状态
int STATUS_COMMITTED = 0;
int STATUS_ROLLED_BACK = 1;
int STATUS_UNKNOWN = 2;
//挂起该事务同步器
default void suspend() {}
//恢复事务同步器
default void resume() {}
//flush 底层的session到数据库
@Override
default void flush() {}
//事务提交前的回调
default void beforeCommit(boolean readOnly) {}
//事务commit/rollback前的回调,用于在事务完成前进行资源清除
default void beforeCompletion() {}
//事务提交后的回调,可以用于在事务成功提交后做的进一步的操作,例如:在数据提交到数据库中后,发送确认的短信或邮件
default void afterCommit() {}
//在事务commit/rollback之后进行回调,例如可以在事务完成后做一些资源清除
default void afterCompletion(int status) {}
}
注册:
先注册才能用
public static void registerSynchronization(TransactionSynchronization synchronization)
throws IllegalStateException {
Assert.notNull(synchronization, "TransactionSynchronization must not be null");
Set<TransactionSynchronization> synchs = synchronizations.get();
if (synchs == null) {
throw new IllegalStateException("Transaction synchronization is not active");
}
synchs.add(synchronization);
}
但是这个set是什么?这就需要从startTransaction开始说起了
/**
* 开启事务
*
* definition 事务属性定义对象
* transaction 事务对象
* suspendedResource 被挂起事务的资源对象,如果当前线程不存在事务 该参数对象null
*
**/
private TransactionStatus startTransaction(TransactionDefinition definition,Object transaction,boolean debugEnabled,@Nullable SuspendedResouceHolder suspendedResources){
//只要事务同步模式 不等于 synchronization_never 事务同步在事务开启事务后生效
boolean newSynchronization =(getTransactionSynchronization)!=SYNCHRONIZATION_NEVER);
//创建一个事务状态对象,newTransaction
DefaultTransactionStatus status = newTransactionStatus(definition,transaction,true,newSynchronization,debugEnable,suspendedResource);
doBegin(transaction,definition);
//事务同步器绑定到当前线程上下文
prepareSynchronization(staus,definition);
return status;
}
/**初始化事务同步器**/
protected void prepareSynchronization(DefaultTransactionStatus status,TransactionDefinition definition){
if(status.isNewSynchronization()){
TransactionSynchronizationManager.setAutoalTransactionActive(
status.hasTransaction());
//记录事务隔离级别到线程上下文
TransactionSynchronizationManager.
setCurrentTransactionIsolationLevel(
definition.getIsolationLevel()!=TransactionDefinition.ISOLATION_DEFAULT?definition.getIsolationLevel():null);
//读写模式
TransactionSynchronizationManager
.setCurrentTransactionReadOnly(definition.isReadOnly());
//名称
TransactionSynchronizationManager
.setCurrentTransactionName(definition.getName());
//激活事务同步器
TransactionSynchronizationManager.initSynchronization();
}
}
/**当前线程上下文激活事务同步功能,开启事务的时候会调用*/
public static void initSynchronization() throws IllegalStateException{
if(isSynchronizationActive()){
throw new IllegalStateException("Cannot activate transaction synchronization - already active");
}
logger.trace("initializing transaction synchronization");
synchronizations.set(new LinkedHashSet<>());
}
小结:仔细的朋友知道了吧,每次创建新spring事务调用startTransation prepareSynchronization 将事务信息放到上下文,initSynchronization初始化空set到synchronizations中! 完美
补充一个细节newTransactionStatus:
把SuppendedResourcesHolder放到DefaultTransactionStatus中,当前上下文创建的是新事务,原事务缓存到TransactionStatus对象中;
protected DefaultTransactionStatus newTransactionStatus(
TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {
boolean actualNewSynchronization = newSynchronization &&
!TransactionSynchronizationManager.isSynchronizationActive();
return new DefaultTransactionStatus(
transaction, newTransaction, actualNewSynchronization,
definition.isReadOnly(), debug, suspendedResources);
}
具体怎么处理的,请见下回 算了……一起说了吧
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
//判断不同的事务传播级别
//PROPAGATION_REQUIRES_NEW开启一个新的事务
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
if (debugEnabled) {
logger.debug("Suspending current transaction, creating new transaction with name [" +
definition.getName() + "]");
}
//把原来的事务挂起,remove解绑ThreadLocal中与当前线程上下文绑定的资源对象,
//SuspendedResourcesHolder中缓存原事务资源对象
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
//创建一个新的事务
return startTransaction(definition, transaction, debugEnabled, suspendedResources);
} catch (RuntimeException | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
}
// ...............
}
分开写吧,显得少点
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
//说明当前线程上下文中存在事务
//回调线程上下文中所有事务同步器,并执行suspend,再把所有事务同步器从线程上下文中移除
List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
try {
//被挂起的资源
Object suspendedResources = null;
if (transaction != null) {
suspendedResources = doSuspend(transaction);
}
//需要挂起当前的事务,所以先缓存当前上下文中的事务,等事务恢复再从缓存中获取,注意后面会把新事务信息放到线程上下文
//获取被挂起的事务名称
String name = TransactionSynchronizationManager.getCurrentTransactionName();
//把线程上下文中的事务名称=null
TransactionSynchronizationManager.setCurrentTransactionName(null);
//获取被挂起事务的读写模式
boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
//线程上下文中的事务读写=非只读 TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
//获取被挂起的事务隔离级别
Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
//线程上下文中的事务中的事务隔离级别=null TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
//被挂起事务的激活状态
boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
//线程上下文中的事务激活状态=false TransactionSynchronizationManager.setActualTransactionActive(false);
// 返回被挂起的资源
return new SuspendedResourcesHolder(
suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
} catch (RuntimeException | Error ex) {
// doSuspend failed - original transaction is still active...
doResumeSynchronization(suspendedSynchronizations);
throw ex;
}
}else if (transaction != null) {
//此时线程上下文中还不存在事务
//挂起事务资源,子类实现,返回原事务的连接对象
Object suspendedResources = doSuspend(transaction);
//原资源缓存在SuspendedResourcesHolder挂起资源对象中
return new SuspendedResourcesHolder(suspendedResources);
} else {
// Neither transaction nor synchronization active.
return null;
}
}
上面这个方法简单来说就是 执行doSuspend 更换线程上下文中的资源对象,将当前的资源对象放到SuspendedResourcesHolder中
private List<TransactionSynchronization> doSuspendSynchronization() {
//获取线程上下文中所有事务同步器
List<TransactionSynchronization> suspendedSynchronizations =
TransactionSynchronizationManager.getSynchronizations();
//遍历所有的事务同步器
for (TransactionSynchronization synchronization : suspendedSynchronizations) {
synchronization.suspend();
}
//所有的事务同步器从线程上下文移除
TransactionSynchronizationManager.clearSynchronization();
return suspendedSynchronizations;
}
直接跳到提交:
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
//事务提交
} finally {
//恢复被挂起事务
cleanupAfterCompletion(status);
}
}
/**
* 当事务完成后会调用,进行一些清理以及恢复操作
*
* @param status 事务状态对象
* @see #doCleanupAfterCompletion
*/
private void cleanupAfterCompletion(DefaultTransactionStatus status) {
//事务状态=已完成
status.setCompleted();
if (status.isNewSynchronization()) {
//清空当前线程上下文与该事务相关信息
TransactionSynchronizationManager.clear();
}
if (status.isNewTransaction()) {
// 钩子方法 子类实现
doCleanupAfterCompletion(status.getTransaction());
}
if (status.getSuspendedResources() != null) {
//该事务中有被挂起的事务
if (status.isDebug()) {
logger.debug("Resuming suspended transaction after completion of inner transaction");
}
Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
//恢复被挂起的事务:被挂起的事务重新绑定到当前线程上下文中
resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
}
}
SuspendedResourcesHolder存在说明有被挂起的事务,恢复事务 :
/**
* 恢复指定的事务
*
* @param transaction 当前线程上下文的事务对象
* @param resourcesHolder 要恢复的事务
* @see #doResume
* @see #suspend
*/
protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)
throws TransactionException {
if (resourcesHolder != null) {
//被挂起的资源
Object suspendedResources = resourcesHolder.suspendedResources;
if (suspendedResources != null) {
//事务恢复逻辑,由子类实现
doResume(transaction, suspendedResources);
}
//被挂起的事务的信息放到当前线程上下文中
List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;
if (suspendedSynchronizations != null) {
TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);
TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);
doResumeSynchronization(suspendedSynchronizations);
}
}
}
当被挂起的事务提交或回滚,从线程上下文中获取它的事务同步器然后进行相应的方法回调