SpringBoot事務(wù)源碼從注解到數(shù)據(jù)庫的全解析
各位Java大俠,上回我們聊了SpringBoot事務(wù)的“表面功夫”,今天咱們來個(gè)深度解剖,看看當(dāng)你瀟灑地寫下@Transactional時(shí),SpringBoot在背后到底干了多少“臟活累活”。準(zhǔn)備好你的IDE,咱們一起開啟源碼之旅!??
第一章:@Transactional的“前世今生”——注解解析全流程 ??
1.1 注解的“出生證明”
當(dāng)你寫@Transactional時(shí),Spring是怎么知道要處理它的?
關(guān)鍵類:TransactionInterceptor、AnnotationTransactionAttributeSource、BeanFactoryTransactionAttributeSourceAdvisor
// 1. 首先,Spring啟動(dòng)時(shí),@EnableTransactionManagement注解開啟事務(wù)支持
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
// 代理模式:CGLIB 還是 JDK動(dòng)態(tài)代理?
AdviceMode mode() default AdviceMode.PROXY;
// 代理順序
int order() default Ordered.LOWEST_PRECEDENCE;
}執(zhí)行流程:
// 簡化版調(diào)用鏈 1. 容器啟動(dòng) → @EnableTransactionManagement生效 2. → 注冊(cè) InfrastructureAdvisorAutoProxyCreator(AOP代理創(chuàng)建器) 3. → 掃描所有Bean,找@Transactional注解的方法 4. → 創(chuàng)建代理對(duì)象,將TransactionInterceptor作為增強(qiáng) 5. → 調(diào)用代理方法時(shí),進(jìn)入TransactionInterceptor.invoke()
1.2 TransactionInterceptor的核心invoke()方法
這是事務(wù)的總?cè)肟?/strong>,讓我們看看它的真面目:
// org.springframework.transaction.interceptor.TransactionInterceptor
public class TransactionInterceptor extends TransactionAspectSupport
implements MethodInterceptor, Serializable {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
// 獲取目標(biāo)類
Class<?> targetClass = (invocation.getThis() != null ?
AopUtils.getTargetClass(invocation.getThis()) : null);
// 關(guān)鍵!調(diào)用父類的invokeWithinTransaction方法
return invokeWithinTransaction(
invocation.getMethod(), // 被調(diào)用的方法
targetClass, // 目標(biāo)類
invocation::proceed // 實(shí)際要執(zhí)行的業(yè)務(wù)方法
);
}
}第二章:invokeWithinTransaction——事務(wù)的“心臟” ??
這才是真正的事務(wù)處理核心,代碼在父類TransactionAspectSupport中:
// org.springframework.transaction.interceptor.TransactionAspectSupport
protected Object invokeWithinTransaction(Method method,
@Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// 1?? 獲取事務(wù)屬性(@Transactional注解的配置)
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ?
tas.getTransactionAttribute(method, targetClass) : null);
// 2?? 確定事務(wù)管理器
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
// 3?? 構(gòu)造方法標(biāo)識(shí)(用于日志和監(jiān)控)
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
// 4?? 聲明式事務(wù)處理
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// ?? 關(guān)鍵!獲取事務(wù)狀態(tài)
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// 5?? 執(zhí)行真正的業(yè)務(wù)邏輯
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 6?? 異常處理:回滾或提交
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
// 7?? 清理線程綁定的資源
cleanupTransactionInfo(txInfo);
}
// 8?? 提交事務(wù)
commitTransactionAfterReturning(txInfo);
return retVal;
}
else {
// 編程式事務(wù)處理(略)
}
}第三章:createTransactionIfNecessary——事務(wù)的“誕生” ??
這個(gè)方法決定了是否創(chuàng)建新事務(wù)、如何傳播事務(wù):
// TransactionAspectSupport.createTransactionIfNecessary
protected TransactionInfo createTransactionIfNecessary(
@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr,
final String joinpointIdentification) {
// 如果transaction屬性為空,則創(chuàng)建一個(gè)空事務(wù)
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// 1. 獲取現(xiàn)有事務(wù)(可能為null)
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
// ?? 關(guān)鍵!調(diào)用事務(wù)管理器的getTransaction方法
status = tm.getTransaction(txAttr);
}
}
// 2. 準(zhǔn)備事務(wù)信息
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
// ...
}3.1 tm.getTransaction()——傳播行為的實(shí)現(xiàn)
這是各種傳播行為的實(shí)現(xiàn)核心,在AbstractPlatformTransactionManager中:
// AbstractPlatformTransactionManager.getTransaction
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
// 1. 獲取事務(wù)定義(沒有則用默認(rèn)值)
TransactionDefinition def = (definition != null ? definition :
TransactionDefinition.withDefaults());
// 2. ?? 獲取現(xiàn)有事務(wù)(檢查當(dāng)前線程是否已有事務(wù))
Object transaction = doGetTransaction();
// 3. 如果當(dāng)前已存在事務(wù)
if (isExistingTransaction(transaction)) {
// ?? 處理嵌套事務(wù)的情況
return handleExistingTransaction(def, transaction, debugEnabled);
}
// 4. 檢查超時(shí)設(shè)置
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException(...);
}
// 5. 當(dāng)前沒有事務(wù),但需要事務(wù)(REQUIRED, REQUIRES_NEW等)
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(...);
}
else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// ?? 關(guān)鍵!掛起null事務(wù)(因?yàn)楫?dāng)前沒有事務(wù))
SuspendedResourcesHolder suspendedResources = suspend(null);
try {
// 6. 開始新事務(wù)
return startTransaction(def, transaction, debugEnabled, suspendedResources);
}
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
else {
// 7. 當(dāng)前不需要事務(wù)(PROPAGATION_SUPPORTS等)
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
}
}3.2 傳播行為的核心:handleExistingTransaction()
讓我們看看不同傳播行為在已有事務(wù)時(shí)的處理:
// AbstractPlatformTransactionManager.handleExistingTransaction
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
// 1. NEVER:不能有事務(wù),有就拋異常
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(...);
}
// 2. NOT_SUPPORTED:不支持事務(wù),掛起當(dāng)前事務(wù)
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
Object suspendedResources = suspend(transaction);
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
// 3. REQUIRES_NEW:掛起當(dāng)前事務(wù),創(chuàng)建新事務(wù)
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
// 掛起當(dāng)前事務(wù)
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
// 開始新事務(wù)
return startTransaction(definition, transaction, debugEnabled, suspendedResources);
}
catch (RuntimeException | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
}
// 4. NESTED:嵌套事務(wù)
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
if (!isNestedTransactionAllowed()) {
throw new NestedTransactionNotSupportedException(...);
}
// 使用保存點(diǎn)(Savepoint)實(shí)現(xiàn)
if (useSavepointForNestedTransaction()) {
// 創(chuàng)建保存點(diǎn)
DefaultTransactionStatus status = prepareTransactionStatus(
definition, transaction, false, false, debugEnabled, null);
status.createAndHoldSavepoint();
return status;
}
else {
// 有些數(shù)據(jù)庫不支持保存點(diǎn),只能開啟新事務(wù)
return startTransaction(definition, transaction, debugEnabled, null);
}
}
// 5. 其他(REQUIRED, SUPPORTS, MANDATORY):加入當(dāng)前事務(wù)
if (isValidateExistingTransaction()) {
// 驗(yàn)證隔離級(jí)別、只讀等設(shè)置是否匹配
}
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return prepareTransactionStatus(
definition, transaction, false, newSynchronization, debugEnabled, null);
}第四章:startTransaction——開啟事務(wù)的“魔法” ??
真正的事務(wù)開啟在這里:
// DataSourceTransactionManager(具體實(shí)現(xiàn))
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
// 1. 如果還沒有連接,從數(shù)據(jù)源獲取
if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
Connection newCon = obtainDataSource().getConnection();
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
// 2. 設(shè)置連接屬性
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
// 3. ?? 關(guān)鍵!設(shè)置隔離級(jí)別
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(
con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
// 4. ?? 關(guān)鍵!關(guān)閉自動(dòng)提交
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
con.setAutoCommit(false); // 就是這一行!
}
// 5. 準(zhǔn)備事務(wù)連接
prepareTransactionalConnection(con, definition);
// 6. 設(shè)置事務(wù)狀態(tài)
txObject.getConnectionHolder().setTransactionActive(true);
// 7. 設(shè)置超時(shí)
int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
// 8. 綁定到當(dāng)前線程
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.bindResource(
obtainDataSource(), txObject.getConnectionHolder());
}
} catch (Throwable ex) {
// 異常處理
DataSourceUtils.releaseConnection(con, obtainDataSource());
throw new CannotCreateTransactionException(...);
}
}看到第4步的con.setAutoCommit(false)了嗎?這就是Spring事務(wù)的基石!沒有它,每個(gè)SQL都會(huì)自動(dòng)提交,就無法回滾了。
第五章:commitTransactionAfterReturning——提交的“藝術(shù)” ??
業(yè)務(wù)方法執(zhí)行成功后,提交事務(wù):
// TransactionAspectSupport.commitTransactionAfterReturning
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
}
// AbstractPlatformTransactionManager.commit
public final void commit(TransactionStatus status) throws TransactionException {
// 1. 檢查事務(wù)是否已完成
if (status.isCompleted()) {
throw new IllegalTransactionStateException(...);
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
// 2. 如果標(biāo)記了回滾,則回滾
if (defStatus.isLocalRollbackOnly()) {
processRollback(defStatus, false);
return;
}
// 3. 檢查是否需要全局回滾
if (!shouldCommitOnGlobalRollbackOnly() &&
defStatus.isGlobalRollbackOnly()) {
processRollback(defStatus, true);
return;
}
// 4. ?? 真正的提交
processCommit(defStatus);
}5.1 processCommit——真正的提交
// AbstractPlatformTransactionManager.processCommit
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
boolean beforeCompletionInvoked = false;
try {
// 1. 觸發(fā)提交前回調(diào)
prepareForCommit(status);
triggerBeforeCommit(status);
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;
// 2. 如果有保存點(diǎn)(嵌套事務(wù))
if (status.hasSavepoint()) {
status.releaseHeldSavepoint(); // 釋放保存點(diǎn),但不提交
return;
}
// 3. 如果是新事務(wù),才真正提交
if (status.isNewTransaction()) {
doCommit(status); // ?? 調(diào)用數(shù)據(jù)源提交
}
// 4. 如果是全局回滾
else if (status.isGlobalRollbackOnly()) {
unexpectedRollback = true;
}
}
catch (UnexpectedRollbackException ex) {
// 異常處理
}
finally {
// 5. 清理資源
cleanupAfterCompletion(status);
}
}
finally {
// ...
}
}5.2 DataSourceTransactionManager.doCommit()
// DataSourceTransactionManager.doCommit
@Override
protected void doCommit(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
try {
con.commit(); // ?? JDBC提交!
} catch (SQLException ex) {
throw new TransactionSystemException("Could not commit JDBC transaction", ex);
}
}第六章:completeTransactionAfterThrowing——回滾的“學(xué)問” ??
業(yè)務(wù)方法拋出異常時(shí),決定是否回滾:
// TransactionAspectSupport.completeTransactionAfterThrowing
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
// 1. 必須要有事務(wù)才需要回滾
if (txInfo != null && txInfo.getTransactionStatus() != null) {
// 2. ?? 關(guān)鍵!判斷是否應(yīng)該回滾
if (txInfo.transactionAttribute != null &&
txInfo.transactionAttribute.rollbackOn(ex)) {
try {
// 3. 執(zhí)行回滾
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
}
catch (TransactionSystemException ex2) {
ex2.initApplicationException(ex);
throw ex2;
}
}
else {
// 4. 不應(yīng)該回滾,則提交
try {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
catch (TransactionSystemException ex2) {
ex2.initApplicationException(ex);
throw ex2;
}
}
}
}6.1 rollbackOn()——回滾判斷邏輯
// RuleBasedTransactionAttribute.rollbackOn
@Override
public boolean rollbackOn(Throwable ex) {
// 1. 遍歷所有回滾規(guī)則
for (RollbackRuleAttribute rule : this.rollbackRules) {
// 2. 檢查異常是否匹配
if (rule.getDepth(ex) >= 0) {
return true; // 匹配,需要回滾
}
}
// 3. 默認(rèn):RuntimeException和Error回滾,CheckedException不?
return (ex instanceof RuntimeException || ex instanceof Error);
}這就是為什么默認(rèn)情況下,IOException等Checked Exception不回滾的原因!
第七章:ThreadLocal的妙用——事務(wù)資源綁定 ??
Spring如何保證同一個(gè)線程內(nèi),多個(gè)DAO操作用同一個(gè)連接?
核心類:TransactionSynchronizationManager
// 內(nèi)部使用ThreadLocal存儲(chǔ)資源
public abstract class TransactionSynchronizationManager {
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");
// 綁定資源到當(dāng)前線程
public static void bindResource(Object key, Object value) throws IllegalStateException {
Map<Object, Object> map = resources.get();
if (map == null) {
map = new HashMap<>();
resources.set(map);
}
map.put(key, value);
}
// 從當(dāng)前線程獲取資源
public static Object getResource(Object key) {
Map<Object, Object> map = resources.get();
if (map == null) {
return null;
}
return map.get(key);
}
}執(zhí)行流程:
// 1. 事務(wù)開始時(shí)
Connection con = dataSource.getConnection();
TransactionSynchronizationManager.bindResource(dataSource, con);
// 2. DAO操作獲取連接時(shí)
public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException {
// 先嘗試從ThreadLocal獲取
ConnectionHolder conHolder = (ConnectionHolder)
TransactionSynchronizationManager.getResource(dataSource);
if (conHolder != null) {
return conHolder.getConnection(); // ? 返回事務(wù)連接
}
// 沒有事務(wù),新建連接
return dataSource.getConnection();
}
// 3. 事務(wù)結(jié)束時(shí)
TransactionSynchronizationManager.unbindResource(dataSource);第八章:自調(diào)用失效的“終極揭秘” ??
現(xiàn)在你明白為什么自調(diào)用事務(wù)不生效了嗎?
@Service
public class UserService {
public void outerMethod() {
// 直接調(diào)用內(nèi)部方法
this.innerMethod(); // ? 事務(wù)不生效!
}
@Transactional
public void innerMethod() {
// 業(yè)務(wù)邏輯
}
}原因:
- Spring事務(wù)基于AOP代理
- 只有通過代理對(duì)象調(diào)用,才會(huì)被
TransactionInterceptor攔截 this.innerMethod()是目標(biāo)對(duì)象內(nèi)部調(diào)用,不會(huì)經(jīng)過代理- 因此
TransactionInterceptor.invoke()不會(huì)執(zhí)行
圖解:
正常調(diào)用:Controller → 代理對(duì)象 → TransactionInterceptor → 目標(biāo)對(duì)象 自調(diào)用:目標(biāo)對(duì)象 → 目標(biāo)對(duì)象(繞過了代理和攔截器?。?/pre>
第九章:調(diào)試技巧——親眼看看事務(wù)流轉(zhuǎn) ??
9.1 開啟調(diào)試日志
# application.yml
logging:
level:
org.springframework.transaction: DEBUG
org.springframework.jdbc.datasource.DataSourceTransactionManager: DEBUG
org.springframework.orm.jpa: DEBUG9.2 觀察日志輸出
DEBUG o.s.j.d.DataSourceTransactionManager: Creating new transaction with name [com.example.UserService.saveUser]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT DEBUG o.s.j.d.DataSourceTransactionManager: Acquired Connection [conn-id] for JDBC transaction DEBUG o.s.j.d.DataSourceTransactionManager: Switching JDBC Connection [conn-id] to manual commit DEBUG o.s.j.d.DataSourceTransactionManager: Initiating transaction commit DEBUG o.s.j.d.DataSourceTransactionManager: Committing JDBC transaction on Connection [conn-id] DEBUG o.s.j.d.DataSourceTransactionManager: Releasing JDBC Connection [conn-id] after transaction
9.3 在關(guān)鍵方法打斷點(diǎn)
TransactionInterceptor.invoke()TransactionAspectSupport.invokeWithinTransaction()AbstractPlatformTransactionManager.getTransaction()DataSourceTransactionManager.doBegin()DataSourceTransactionManager.doCommit()/doRollback()
第十章:手寫一個(gè)簡化版事務(wù)管理器(理解原理) ???
理解了原理,讓我們手寫一個(gè)極簡版:
// 1. 事務(wù)管理器
public class SimpleTransactionManager {
private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<>();
private static ThreadLocal<Boolean> transactionActive = ThreadLocal.withInitial(() -> false);
public static void begin() throws SQLException {
if (transactionActive.get()) {
return; // 已存在事務(wù),支持傳播
}
Connection conn = DataSourceUtils.getConnection();
conn.setAutoCommit(false); // 關(guān)鍵!
connectionHolder.set(conn);
transactionActive.set(true);
}
public static void commit() throws SQLException {
if (!transactionActive.get()) {
return;
}
Connection conn = connectionHolder.get();
conn.commit();
conn.setAutoCommit(true);
conn.close();
connectionHolder.remove();
transactionActive.set(false);
}
public static void rollback() throws SQLException {
if (!transactionActive.get()) {
return;
}
Connection conn = connectionHolder.get();
conn.rollback();
conn.setAutoCommit(true);
conn.close();
connectionHolder.remove();
transactionActive.set(false);
}
public static Connection getConnection() {
return connectionHolder.get();
}
}
// 2. 事務(wù)注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SimpleTransactional {
Class<? extends Throwable>[] rollbackFor() default {RuntimeException.class};
}
// 3. 動(dòng)態(tài)代理處理器
public class TransactionProxy implements InvocationHandler {
private Object target;
public TransactionProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method targetMethod = target.getClass().getMethod(method.getName(),
method.getParameterTypes());
// 檢查是否有@SimpleTransactional注解
if (targetMethod.isAnnotationPresent(SimpleTransactional.class)) {
SimpleTransactional annotation = targetMethod.getAnnotation(SimpleTransactional.class);
try {
// 開啟事務(wù)
SimpleTransactionManager.begin();
// 執(zhí)行業(yè)務(wù)方法
Object result = method.invoke(target, args);
// 提交事務(wù)
SimpleTransactionManager.commit();
return result;
} catch (Throwable e) {
// 判斷是否需要回滾
for (Class<? extends Throwable> rollbackEx : annotation.rollbackFor()) {
if (rollbackEx.isAssignableFrom(e.getClass())) {
SimpleTransactionManager.rollback();
break;
}
}
throw e;
}
} else {
return method.invoke(target, args);
}
}
}總結(jié):事務(wù)的完整生命周期 ??
- 代理創(chuàng)建:Spring容器啟動(dòng)時(shí),為
@Transactional標(biāo)注的Bean創(chuàng)建代理 - 方法調(diào)用:通過代理調(diào)用方法,進(jìn)入
TransactionInterceptor.invoke() - 獲取屬性:解析
@Transactional注解的配置 - 決策事務(wù):根據(jù)傳播行為,決定新建、加入還是掛起事務(wù)
- 開啟事務(wù):獲取數(shù)據(jù)庫連接,設(shè)置
autoCommit=false - 執(zhí)行業(yè)務(wù):調(diào)用原始業(yè)務(wù)方法
- 異常處理:根據(jù)異常類型決定回滾或提交
- 提交/回滾:提交事務(wù)或回滾事務(wù)
- 清理資源:關(guān)閉連接,清理ThreadLocal
最后的思考 ??
通過源碼分析,我們發(fā)現(xiàn)SpringBoot事務(wù)的本質(zhì)是:
- 基于AOP的攔截
- 基于ThreadLocal的資源管理
- 基于JDBC Connection的autoCommit控制
理解了這些,你就能:
- 解釋為什么自調(diào)用失效
- 理解傳播行為的底層實(shí)現(xiàn)
- 知道事務(wù)同步管理器的工作原理
- 調(diào)試復(fù)雜的事務(wù)問題
- 甚至自己實(shí)現(xiàn)一個(gè)簡單的事務(wù)框架
下次遇到事務(wù)問題,不要只是重啟應(yīng)用,打開調(diào)試日志,跟蹤源碼,你會(huì)發(fā)現(xiàn)每個(gè)異常背后,都有一個(gè)清晰的邏輯鏈。這就是從“會(huì)用框架”到“懂框架”的蛻變!??
源碼如詩,每一行都藏著智慧。讀懂了它,你就讀懂了SpringBoot的靈魂。 ? ??
(現(xiàn)在,你可以自信地在團(tuán)隊(duì)分享:“我知道@Transactional的每一行代碼在做什么!” 這種感覺,比加薪還棒!????)
到此這篇關(guān)于SpringBoot事務(wù)源碼從注解到數(shù)據(jù)庫的“奇幻漂流”的文章就介紹到這了,更多相關(guān)SpringBoot事務(wù)源碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot 中的 @Transactional 事務(wù)基本作用及注意事項(xiàng)示例詳解
- SpringBoot事務(wù)注解@Transactional失效場景與解決方案
- Springboot @Transactional大事務(wù)處理的幾點(diǎn)建議
- SpringBoot?@Transactional事務(wù)不生效排查方式
- springboot中事務(wù)管理@Transactional的注意事項(xiàng)與使用場景
- Springboot中@Transactional注解與異常處理機(jī)制方式
- Java中SpringBoot的@Transactional原理
- 解決SpringBoot中使用@Transactional注解遇到的問題
- 詳解在SpringBoot中@Transactional事物操作和事物無效問題排查
相關(guān)文章
java從控制臺(tái)接收一個(gè)數(shù)字的實(shí)例詳解
這篇文章主要介紹了java從控制臺(tái)接收一個(gè)數(shù)字的實(shí)例詳解的相關(guān)資料,這里提供實(shí)例代碼,注釋說明清晰,需要的朋友可以參考下2017-07-07
在SpringBoot項(xiàng)目中實(shí)現(xiàn)圖片縮略圖功能的三種方案
本文介紹了在SpringBoot項(xiàng)目中實(shí)現(xiàn)圖片縮略圖的三種方案:使用Thumbnailator庫、JavaAWT原生庫以及集成MinIO自動(dòng)生成縮略圖,每種方案都詳細(xì)介紹了實(shí)現(xiàn)步驟,并提供了完整的案例,需要的朋友可以參考下2025-10-10
JDK8中的HashMap初始化和擴(kuò)容機(jī)制詳解
這篇文章主要介紹了JDK8中的HashMap初始化和擴(kuò)容機(jī)制,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
VerifyCodeServlet(一次性驗(yàn)證碼)
這篇文章主要介紹了VerifyCodeServlet一次性驗(yàn)證碼的使用方法2017-05-05
SpringBoot使用Hibernate攔截器實(shí)現(xiàn)時(shí)間自動(dòng)注入的操作代碼
這篇文章主要介紹了SpringBoot使用Hibernate攔截器實(shí)現(xiàn)時(shí)間自動(dòng)注入的操作代碼,主要包括hibernate攔截器的相關(guān)知識(shí),結(jié)合實(shí)例代碼給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-10-10
基于Spring Boot的Environment源碼理解實(shí)現(xiàn)分散配置詳解
這篇文章主要給大家介紹了基于Spring Boot的Environment源碼理解實(shí)現(xiàn)分散配置的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08
java實(shí)現(xiàn)幸運(yùn)抽獎(jiǎng)系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)幸運(yùn)抽獎(jiǎng)系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07
java 獲取數(shù)據(jù)庫連接的實(shí)現(xiàn)代碼
本篇文章是對(duì)在java中獲取數(shù)據(jù)庫連接的實(shí)現(xiàn)代碼進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05

