一箕慧、官網(wǎng)地址:
https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/data-access.html#
Transaction
二雳攘、實現(xiàn)方式:
2.1 通過xml配置:
2.1.1配置transanctionManager, 屬性 dataSource
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
2.1.2 基于Aop 配置事務(wù)增強 <tx> 標簽 是transaction 提供的標簽,在這里可以配置指定某些方法定義事務(wù)的傳播行為汁尺,隔離級別。
2.2 通過注解配置:
開啟spring 注解事務(wù)的注解:@EnableTransactionManagement
在要加事務(wù)管理的類或方法上加@Transactional多律,如果需要對事務(wù)的其他屬性進行配置時痴突,即在注解上面配置相關(guān)屬性即可。
2.3 編程式事務(wù):
1 定義TransactionDefinition 作為transactionManager的入?yún)l件來獲取TransactionStatus狼荞,其中DefaultTransactionDefinition 定義了事務(wù)的屬性辽装。
TransactionDefinition definition = new DefaultTransactionDefinition();
TransactionStatus status = txManager.getTransaction(definition);
try{
//業(yè)務(wù)
txManager.commit(status);
}catch(Exception e){
//出現(xiàn)異常手動回滾
txManager.rollback(status );
}
還有一種直接獲取TransactionStatus 并將他設(shè)置成rollbackOnly
public void resolvePosition() {
try {
// some business logic...
} catch (NoProductInStockException ex) {
// trigger rollback programmatically
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
2 spring 還提供了事務(wù)模版用來管理事務(wù):
TransactionTemplate 執(zhí)行 execute();方法來完成相關(guān)事務(wù)操作。
可以自己在此基礎(chǔ)上造個輪子:
package com.chen.springboot.bootlearn.template;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
@Component
public class SpringTransaction {
@Autowired
private TransactionTemplate transactionTemplate; // TransactionTemplate 作為spring bean維護
//提供一個模版方法 子類重寫具體業(yè)務(wù)
public Object execute(TransactionTemplates templates) {
Object result = new Object();
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
try {
templates.lock();
} finally {
System.out.println("Lock");
}
try {
templates.check();
} finally {
System.out.println("Check");
}
try {
templates.process();
} finally {
System.out.println("Process");
}
}
});
return result;
}
}
遇到需要調(diào)用事務(wù)的時候 直接執(zhí)行 execute()方法即可
@Override
public Object addCount(User user) {
Object object = new Object();
transaction.execute(new TransactionTemplates() {
@Override
public void check() {
}
@Override
public void lock() {
}
@Override
public void process() {
}
});
return object;
}
三 事務(wù)API
Spring事務(wù)核心的API:
3.1 : PlatformTransactionManager,平臺級的事務(wù)管理器相味,它抽象定義了事務(wù)管理行為拾积,不同
的事務(wù)管理實現(xiàn)實現(xiàn)該接口。我們編程面向該接口丰涉。繼承關(guān)系圖如下所示:
3.1.1 抽象方法也很簡單:
3.2 : TransactionDefinition:事務(wù)定義拓巧。Spring 事務(wù)管理框架將為我們管理事務(wù),但不清楚該
如何替我們管理一死,我們就通過事務(wù)定義來定義我們需要的事務(wù)管理信息肛度,把這些信息給事務(wù)
管理器,它就知道我們的意圖了投慈。
接口 的結(jié)構(gòu)圖如下所示:
繼承關(guān)系圖:
3.3:TransactionStatus 事務(wù)狀態(tài)承耿,持有事務(wù)的狀態(tài)信息。事務(wù)管理代碼可通過它獲取事務(wù)狀態(tài)伪煤、
以及顯式地設(shè)置回滾(代替異常的方式)加袋。它繼承了 SavePoint 接口。在它的實現(xiàn)中會持有事
務(wù)的很多對象:如事務(wù)對象带族、被掛起的事務(wù)資源等锁荔。
從 TransactionManager 中獲取事務(wù)得到它,提交/回滾事務(wù)時要給入它:
類結(jié)構(gòu)圖:
繼承關(guān)系圖:
四 具體實現(xiàn)流程:
驗證:DataSourceTransactionManager
DataSourceTransactionManager 是基于 jdbc connection 的本地事務(wù)管理實現(xiàn)。多個方法
調(diào)用參與到同一個事務(wù)阳堕,是通過共用 connection 來完成的跋理。
通過不同的事務(wù)傳播屬性,執(zhí)行方法時也會有不同恬总。驗證不同傳播屬性對事務(wù)的影響:
方法一 required --- 方法二 required
方法一 required --- 方法二 requires_new
方法一 required --- 方法二 nested (當(dāng)前存在事務(wù) 則嵌套在事務(wù)內(nèi)執(zhí)行前普,沒有事務(wù)則新開啟一個事務(wù))
具體代碼 主要集中在 AbstractPlatformTransactionManager
典型的模板方法的設(shè)計模式, 子類調(diào)用父類的 getTransaction(),這個方法時不能不能不重寫的方法壹堰,子類只能重寫里面的 doGetTransaction() 封裝事務(wù)對象拭卿,isExistingTransaction():判斷是否存在事務(wù),handleExistingTransaction():存在事務(wù)的處理流程,doBegin():開啟事務(wù)。doCommit():提交事務(wù)贱纠,doRollback():回滾事務(wù)峻厚。
@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
//獲取事務(wù)對象 TransactionObject 由子類去實現(xiàn)
Object transaction = doGetTransaction();
if (definition == null) {
// Use defaults if no transaction definition given.
definition = new DefaultTransactionDefinition();
}
if (isExistingTransaction(transaction)) {//是否存在事務(wù)
//存在事務(wù)如何處理
return handleExistingTransaction(definition, transaction, debugEnabled);
}
// 不存在事務(wù)檢查事務(wù)傳播行為
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
SuspendedResourcesHolder suspendedResources = suspend(null);
try {
//封裝: DefaultTransactionStatus : 1事務(wù)對象 2是否是新事務(wù) 3 事務(wù)同步器是否開啟默認是開著的 4 是否 開啟只讀控制。 5 掛起的資源
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
//開啟事務(wù)
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
else {
// 傳播行為 為其他的時候就不做任何處理谆焊,也要封裝一個 TransactionStatus對象
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + definition);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
}
}
具體執(zhí)行流程如下圖所示:
獲取事務(wù)對象:
@Override
protected Object doGetTransaction() {
// 每來一個事務(wù)時都要創(chuàng)建一個事務(wù)對象
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
txObject.setSavepointAllowed(isNestedTransactionAllowed());
ConnectionHolder conHolder =
//從當(dāng)前ThreadLocal (TransactionSynchronizationManager) 中獲取一個連接 并放到事務(wù)對象惠桃。
(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
TransactionSynchronizationManager 為了保證多線程下事務(wù)不出現(xiàn)混亂,通過ThreadLocal 來保證線程的同步.
public abstract class TransactionSynchronizationManager {
private static final Log logger = LogFactory.getLog(TransactionSynchronizationManager.class);
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<>("Transactional resources");
private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
new NamedThreadLocal<>("Transaction synchronizations");
private static final ThreadLocal<String> currentTransactionName =
new NamedThreadLocal<>("Current transaction name");
private static final ThreadLocal<Boolean> currentTransactionReadOnly =
new NamedThreadLocal<>("Current transaction read-only status");
private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
new NamedThreadLocal<>("Current transaction isolation level");
private static final ThreadLocal<Boolean> actualTransactionActive =
new NamedThreadLocal<>("Actual transaction active");
···················
}
判斷是否存在事務(wù):
@Override
protected boolean isExistingTransaction(Object transaction) {
//判斷事務(wù)對象中是否存在連接持有器辖试,連接持有器中的事務(wù)是否被激活
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
}
對掛起事務(wù)的恢復(fù)
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);
}
}
}