摘要:支持聲明式事務,通過注解控制方法是否支持事務。聲明式事務,基于實現,將具體業務和業務邏輯解耦。該級別下事務順序執行,阻止上面的缺陷,開銷很大。
問題引入
- Spring中事務傳播有哪幾種,分別是怎樣的?
- 理解注解事務的自動配置?
- SpringBoot啟動類為什么不需要加@EnableTransactionManagement注解?
- 聲明式事務的實現原理?(待補充)
系統開發中必然與數據打交道,事務管理必不可少。Spring支持聲明式事務,通過@Transactional注解控制方法是否支持事務。聲明式事務,基于AOP實現,將具體業務和業務邏輯解耦。
Spring提供了@EnableTransactionManagement注解在配置類(啟動類)上啟用支持事務,此時Spring會自動掃描具有@Transactional注解的類和方法。該注解相當于xml配置方式的
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(TransactionManagementConfigurationSelector.class)public @interface EnableTransactionManagement { boolean proxyTargetClass() default false; AdviceMode mode() default AdviceMode.PROXY; // 代理模式 int order() default Ordered.LOWEST_PRECEDENCE; // LOWEST_PRECEDENCE最低優先級,所以在執行鏈的最外面,而自己實現的AOP攔截器優先級都高于事務,所以被嵌套在里面,越貼近業務代碼。}
@Transactional注解可以應用于類和方法。聲明類時,該注解默認作用于類和子類的所有方法,應用于public方法才有效;父類方法要加入同等級別的注解,需要多帶帶聲明。
@Target({ElementType.TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Inherited@Documentedpublic @interface Transactional { @AliasFor("transactionManager") String value() default ""; // 用來確定目標事務管理器 @AliasFor("value") String transactionManager() default ""; // 事務的傳播,默認Propagation.REQUIRED Propagation propagation() default Propagation.REQUIRED; // 事務隔離級別,默認是Isolation.DEFAULT Isolation isolation() default Isolation.DEFAULT; // 事務超時時間,默認是-1 int timeout() default TransactionDefinition.TIMEOUT_DEFAULT; // 指定事務是否為只讀事務,默認為false,僅僅是個提示 boolean readOnly() default false; // 標識能觸發事務回滾的異常類型,默認是RuntimeException和Error,不包含檢查異常。 Class extends Throwable>[] rollbackFor() default {}; // 標識哪些異常不需要回滾事務 Class extends Throwable>[] noRollbackFor() default {}; String[] noRollbackForClassName() default {}; String[] rollbackForClassName() default {};}
其中,isolation和timeout兩個屬性僅對新啟動的事務有效,專為Propagation.REQUIRED和Propagation.REQUIRES_NEW使用而設計。
Propagation定義了事務的傳播,一共有7種級別。
public enum Propagation { REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED), SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS), MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY), REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW), NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED), NEVER(TransactionDefinition.PROPAGATION_NEVER), NESTED(TransactionDefinition.PROPAGATION_NESTED); private final int value; Propagation(int value) { this.value = value; } public int value() { return this.value; }}
最根本的區別是NESTED還在一個事務中,但是與主事務一塊提交。
// TransactionalServiceImpl@Transactional(propagation = Propagation.REQUIRED)@Overridepublic void testPropagation() { stuService.saveParent(); stuService.saveChildren(); int a = 1 / 0;}// StuServiceImpl/* 測試事務傳播 */@Transactional(propagation = Propagation.NESTED) // 切換NESTED/REQUIRES_NEW@Overridepublic void saveParent() { Stu stu = new Stu(); stu.setName("parent"); stu.setScore(100); stuMapper.insert(stu);}@Transactional(propagation = Propagation.NESTED)@Overridepublic void saveChildren() { saveChild1(); int a = 1 / 0; saveChild2();}
在代理模式(默認)下,僅攔截通過代理傳入的外部方法調用。這意味著同一個目標對象內部的方法調用,即使調用的方法標記有@Transactional,也不會在運行時導致事務攔截。
// 同一個類@Transactional(propagation = Propagation.REQUIRED)@Overridepublic void saveChildren() { saveChild1(); int a = 1 / 0; saveChild2();}@Transactional(propagation = Propagation.REQUIRES_NEW)public void saveChild1() { Stu stu = new Stu(); stu.setName("child-1"); stu.setScore(60); stuMapper.insert(stu);}
參考官方文檔
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction at runtime even if the invoked method is marked with @Transactional. Also, the proxy must be fully initialized to provide the expected behaviour so you should not rely on this feature in your initialization code, i.e. @PostConstruct.在代理模式下(默認),只有通過代理進入的外部方法調用才會被攔截。 這意味著自調用實際上是目標對象中的一個方法調用目標對象的另一個方法,即使被調用的方法用@Transactional 標記,也不會在運行時導致實際事務。 此外,代理必須完全初始化以提供預期的行為,因此您不應在初始化代碼中依賴此功能,即@PostConstruct。
public enum Isolation { DEFAULT(TransactionDefinition.ISOLATION_DEFAULT), READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED), READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED), REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ), SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE); private final int value; Isolation(int value) { this.value = value; } public int value() { return this.value; }}
Spring事務隔離級別共有5種,隔離級別的設置依賴當前數據庫是否支持。
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
SpringBoot加載spring.factories時,會加載事務配置類TransactionAutoConfiguration,內部有開啟事務管理的配置。
// ~TransactionAutoConfiguration中的內部類@Configuration(proxyBeanMethods = false)@ConditionalOnBean(TransactionManager.class)@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)public static class EnableTransactionManagementConfiguration { @Configuration(proxyBeanMethods = false) @EnableTransactionManagement(proxyTargetClass = false) @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false) public static class JdkDynamicAutoProxyConfiguration { } @Configuration(proxyBeanMethods = false) @EnableTransactionManagement(proxyTargetClass = true) @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true) public static class CglibAutoProxyConfiguration { }}
在應用系統調用聲明@Transactional 的目標方法時,Spring Framework 默認使用 AOP 代理,結合AOP和事務元數據(注解)在代碼運行時生成一個代理對象,根據@Transactional 的屬性配置信息,這個代理對象決定該聲明@Transactional 的目標方法是否由攔截器 TransactionInterceptor 來使用攔截,在 TransactionInterceptor 攔截時,會在目標方法開始執行之前創建并加入事務,并執行目標方法的邏輯, 最后根據執行情況是否出現異常,利用抽象事務管理器AbstractPlatformTransactionManager 操作數據源 DataSource 提交或回滾事務。
事務管理的框架是由抽象事務管理器 AbstractPlatformTransactionManager 來提供的,而具體的底層事務處理實現由 PlatformTransactionManager 的具體實現類來實現,如事務管理器 DataSourceTransactionManager。不同的事務管理器管理不同的數據資源 DataSource,比如 DataSourceTransactionManager 管理 JDBC 的 Connection。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/124120.html
摘要:基于和命名空間的聲明式事務管理目前推薦的方式,其最大特點是與結合緊密,可以充分利用切點表達式的強大支持,使得管理事務更加靈活。基于的全注解方式將聲明式事務管理簡化到了極致。 Java面試通關手冊(Java學習指南):https://github.com/Snailclimb/Java_Guide 歷史回顧:可能是最漂亮的Spring事務管理詳解 Spring事務管理 Spring支持兩...
摘要:當你真正到公司里面從事了幾年開發之后,你就會同意我的說法利用找工作,需要的就是項目經驗,項目經驗就是理解項目開發的基本過程,理解項目的分析方法,理解項目的設計思 Java就是用來做項目的!Java的主要應用領域就是企業級的項目開發!要想從事企業級的項目開發,你必須掌握如下要點: 1、掌握項目開發的基本步驟 2、具備極強的面向對象的分析與設計技巧 3、掌握用例驅動、以架構為核心的主流開發...
摘要:前言如題,今天介紹的聲明式事務。提供一個注解在配置類上來開啟聲明式事務的支持。而在配置里還開啟了對聲明式事務的支持,代碼如下所以在中,無須顯式開啟使用注解。源碼下載后語以上為聲明式事務的教程。 微信公眾號:一個優秀的廢人如有問題或建議,請后臺留言,我會盡力解決你的問題。 前言 如題,今天介紹 SpringBoot 的 聲明式事務。 Spring 的事務機制 所有的數據訪問技術都有事務處...
閱讀 939·2021-11-22 12:09
閱讀 3710·2021-09-27 13:36
閱讀 1396·2021-08-20 09:37
閱讀 4016·2019-12-27 12:22
閱讀 2360·2019-08-30 15:55
閱讀 2364·2019-08-30 13:16
閱讀 2822·2019-08-26 17:06
閱讀 3440·2019-08-23 18:32