Spring是如何傳播事務的?
Spring框架通過聲明式事務管理來傳播事務,主要依賴于AOP(面向切面編程)和事務攔截器來實現。Spring的事務傳播機制是基于Java Transaction API (JTA) 或者本地資源管理器(如Hibernate、JDBC等)來完成的。以下是Spring如何實現事務傳播的基本過程:
1. 配置事務管理器
首先,你需要配置一個合適的事務管理器,這取決于你使用的數據訪問技術。例如,如果你使用的是JDBC或MyBatis,你可以選擇DataSourceTransactionManager
;如果使用的是Hibernate,則可以使用HibernateTransactionManager
;對于分布式事務,可以使用JtaTransactionManager
。
2. 使用@Transactional注解
在需要事務管理的方法或類上添加@Transactional
注解,并設置相應的傳播行為屬性(propagation)。這是最常用的聲明式事務管理方式。例如:
@Transactional(propagation = Propagation.REQUIRED)
public void performService() {// 業務邏輯代碼
}
3. AOP自動代理
當你配置了事務管理器并使用了@Transactional
注解后,Spring會自動創建代理對象。當調用被@Transactional
標注的方法時,實際上是通過這個代理對象進行調用。代理對象會在方法執行前后進行事務的開啟、提交或回滾操作。
4. 事務傳播行為的應用
根據不同的傳播行為設置,Spring會決定當前方法是否應該在已有事務中運行,還是應該啟動新事務,或者以其他方式處理事務。比如,Propagation.REQUIRED
表示如果當前存在事務,則加入該事務;如果沒有事務,則創建一個新事務。
5. 異常處理
默認情況下,Spring會在遇到運行時異常或錯誤時回滾事務。不過,你可以通過@Transactional
注解的rollbackFor和noRollbackFor屬性來自定義哪些異常發生時應回滾事務,哪些不應回滾。
通過這種方式,Spring能夠靈活地管理和傳播事務,確保業務邏輯的一致性和完整性。同時,它也提供了足夠的靈活性,讓開發者可以根據實際需求定制事務的行為。
Spring事務傳播行為
Spring事務傳播行為定義了在存在或不存在當前事務時,如何處理新方法的事務。以下是各個傳播行為的具體說明及其典型應用場景:
-
REQUIRED(默認值)
- 描述: 如果當前存在事務,則加入該事務;如果不存在事務,則創建一個新事務。
- 應用場景: 大多數情況下,這是最常用的設置。例如,在服務層中執行數據庫操作,通常希望這些操作在同一事務中進行,以確保數據一致性。
-
SUPPORTS
- 描述: 如果當前存在事務,則加入該事務;如果不存在事務,則以非事務方式繼續運行。
- 應用場景: 適用于那些不需要事務性保障的操作,但如果被其他需要事務的操作調用時,可以共享外部事務。比如讀取一些不敏感的數據信息。
-
MANDATORY
- 描述: 如果當前存在事務,則加入該事務;如果不存在事務,則拋出異常。
- 應用場景: 當你確定某些業務邏輯必須在事務內執行時使用。這可以作為一種安全措施,確保不會意外地以非事務方式調用關鍵操作。
-
REQUIRES_NEW
- 描述: 創建一個新的事務,如果當前存在事務,則暫停當前事務。
- 應用場景: 需要確保某個操作獨立于其他事務,即使外圍事務回滾也不受影響。例如,記錄審計日志或發送通知消息,這些操作應獨立于業務邏輯事務。
-
NOT_SUPPORTED
- 描述: 以非事務方式執行操作,如果當前存在事務,則暫停當前事務。
- 應用場景: 對于性能要求較高且不需要事務保證的操作,如查詢操作,避免不必要的事務開銷。
-
NEVER
- 描述: 以非事務方式執行,如果當前存在事務,則拋出異常。
- 應用場景: 確保某些方法絕對不會在事務上下文中被調用,適合那些明確不應該與事務關聯的操作。
-
NESTED
- 描述: 如果當前存在事務,則在嵌套事務內執行。如果當前不存在事務,則其行為類似于
REQUIRED
。 - 應用場景: 當你需要支持部分回滾時使用。例如,如果你在一個大事務中有多個步驟,并且希望在某一步驟失敗時僅回滾該步驟而不是整個事務。
- 描述: 如果當前存在事務,則在嵌套事務內執行。如果當前不存在事務,則其行為類似于
下面是一個簡單的示例展示如何使用這些傳播行為:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@Service
public class TransactionalService {@Autowiredprivate AnotherTransactionalService anotherService;@Transactional(propagation = Propagation.REQUIRED)public void required() {// 業務邏輯anotherService.anotherMethod();}@Transactional(propagation = Propagation.REQUIRES_NEW)public void requiresNew() throws Exception {// 業務邏輯anotherService.anotherMethod();}// 其他傳播行為的示例略...
}
在這個例子中,required()
方法使用了Propagation.REQUIRED
傳播行為,意味著如果當前有事務,它會加入這個事務;如果沒有,就會創建一個新事務。而requiresNew()
方法使用了Propagation.REQUIRES_NEW
,這會保證每次調用時都會有一個獨立的新事務開始,即使在外圍已經有事務存在。注意,具體到每個傳播行為的實現細節都依賴于Spring框架底層的事務管理機制以及所使用的事務管理器(如JpaTransactionManager、DataSourceTransactionManager等)。