1.引
上一節(jié)已經(jīng)分析了了在單service單方法下的事物創(chuàng)建過程以及其后續(xù)處理工作娶桦,當然還缺少真正創(chuàng)建事物的分析,本篇接續(xù)蓬蝶。先來回顧一下事物創(chuàng)建的代碼片段:
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
// 創(chuàng)建DefaultTransactionStatus對象實例
DefaultTransactionStatus status = newTransactionStatus(
definition,
transaction,
true,
newSynchronization,
debugEnabled,
suspendedResources);
// 開啟事物
doBegin(transaction, definition);
// 初始化事務同步耳贬。
prepareSynchronization(status, definition);
return status;
}
2.創(chuàng)建DefaultTransactionStatus對象
/**
* 創(chuàng)建DefaultTransactionStatus實例
* Create a TransactionStatus instance for the given arguments.
*/
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);
}
//構造方法
public DefaultTransactionStatus(
@Nullable Object transaction,
boolean newTransaction,
boolean newSynchronization,
boolean readOnly,
boolean debug,
@Nullable Object suspendedResources) {
this.transaction = transaction;
this.newTransaction = newTransaction;
this.newSynchronization = newSynchronization;
this.readOnly = readOnly;
this.debug = debug;
this.suspendedResources = suspendedResources;
}
3.開啟事物
針對不同的事物管理器會有不同的事物開啟過程,本例我們只看DataSourceTransactionManager下的事物開啟過程:
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
// ConnectionHolder簡介:包裝JDBC連接的資源容器碌燕。DataSourceTransactionManager將該類的實例綁定到特定數(shù)據(jù)源的線程误证。
// 如果txObject沒有ConnectionHolder或者connectionHolder并沒有加同步鎖,則為其設置ConnectionHolder并加同步鎖
if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
// 從數(shù)據(jù)源獲取連接
Connection newCon = obtainDataSource().getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
// 設置DataSourceTransactionObject的ConnectionHolder對象
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
// 設置同步鎖標記
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
// 從ConnectionHolder對象中獲取連接
con = txObject.getConnectionHolder().getConnection();
// 設置連接的只讀屬性和數(shù)據(jù)庫事物隔離級別
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
// so we don't want to do it unnecessarily
// (for example if we've explicitly configured the connection pool to set it already).
// 如果需要,切換到手動提交修壕。
// 在某些JDBC驅動程序中愈捅,這是非常昂貴的,所以我們不想做不必要的事情
// (例如慈鸠,如果我們已經(jīng)顯式地配置了連接池來設置它)蓝谨。
// 所以:如果連接設置了自動提交,這里要將其轉換為手動提交
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
if (logger.isDebugEnabled()) {
logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
}
con.setAutoCommit(false);
}
// 設置當前事物只讀,如果定義了只讀屬性為true
prepareTransactionalConnection(con, definition);
// 設置當前事物為已激活
txObject.getConnectionHolder().setTransactionActive(true);
// 設置超時時間(如果超時時間不等于默認超時時間)
int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
// Bind the connection holder to the thread.
// 綁定ConnectionHolder到當前線程
if (txObject.isNewConnectionHolder()) {
// 即TransactionSynchronizationManager類的resources對象:
// 該對象保存每個事物線程對應的connection或session等類型的資源
// private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal<>("Transactional resources");
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
}
}
// 異常處理
catch (Throwable ex) {
if (txObject.isNewConnectionHolder()) {
DataSourceUtils.releaseConnection(con, obtainDataSource());
txObject.setConnectionHolder(null, false);
}
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
}
}
該方法也比較簡單,相信大家都能看懂青团,其中關于ConnectionHolder(前文沒有講解)對象譬巫,也已經(jīng)在注釋里做過介紹了。
4.初始化事物同步
/**
* 根據(jù)需要初始化事務同步督笆。
* Initialize transaction synchronization as appropriate.
*/
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
if (status.isNewSynchronization()) {
// 設置事物激活狀態(tài)
TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
// 設置事物隔離級別
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ? definition.getIsolationLevel() : null);
// 設置事物只讀屬性
TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
// 設置事物名稱
TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
// 激活當前線程的事務同步芦昔。事務管理器在事務開始時調用。
TransactionSynchronizationManager.initSynchronization();
}
}
總體來講上面的內容還是比較簡單的娃肿,不做過多的分析了烟零。
5.其他事物特性處理
以上分析的都是基于單service下單個方法調用的事物創(chuàng)建過程,且當前不存在事物咸作,那么對于其它的事物的特性呢?接下來就分析一下其他的特性宵睦,其實前面的章節(jié)已經(jīng)有過簡單的介紹了记罚,這里再詳細分析下。對于PROPAGATION_NESTED特性會直接拋出異常壳嚎。
那么下面介紹一下PROPAGATION_SUPPORTS桐智、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER特性事物處理過程烟馅,先來看一下代碼片段:
// Create "empty" transaction: no actual transaction, but potentially synchronization.
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);
protected final DefaultTransactionStatus prepareTransactionStatus(
TransactionDefinition definition,
@Nullable Object transaction,
boolean newTransaction,
boolean newSynchronization,
boolean debug,
@Nullable Object suspendedResources) {
DefaultTransactionStatus status = newTransactionStatus(
definition,
transaction,
newTransaction,
newSynchronization,
debug,
suspendedResources);
prepareSynchronization(status, definition);
return status;
}
從代碼里可以看到说庭,該處理與創(chuàng)建真正的事物的過程相似,只是傳遞的參數(shù)不同罷了郑趁。大家可以多設定幾種傳播特性刊驴,跟蹤一下代碼即可。