国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Spring事物基礎知識及AOP相關陷阱分析

Spring事物基礎知識及AOP相關陷阱分析

2021-12-22 13:24去哪里吃魚 Java教程

這篇文章主要介紹了Spring事物基礎知識及AOP相關陷阱,在平時的實際開發中經常會遇到,只有深入了解了其中的原理,才會在工作中能夠有效應對

一、事務的定義

事務(Transaction),是指訪問并可能更新數據庫中各種數據項的一個程序執行單元(unit),是恢復和并發控制的基本單位。

事務的產生,其實是為了當應用程序訪問數據庫的時候,事務能夠簡化我們的編程模型,不需要我們去考慮各種各樣的潛在錯誤和并發問題.

 

二、事務的屬性

事務具有4個屬性,簡稱 ACID

 

  屬性 說明
Atomicity 原子性 一個事務是一個不可分割的工作單位,事務中包括的操作要么都做,要么都不做。
Consistency 一致性 事務執行的結果必須是使數據庫從一個一致性狀態c0變到另一個一致性狀態c1
Isolation 隔離性 一個事務的執行不能被其他事務干擾。即一個事務內部的操作及使用的數據對并發的其他事務是隔離的,并發執行的各個事務之間不能互相干擾。
Durability 持久性 指一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。接下來的其他操作或故障不應該對其有任何影響。

 

三、Spring 事務的隔離級別

當多個線程都開啟事務操作數據庫中的數據時,數據庫系統要能進行隔離操作,以保證各個線程獲取數據的準確性。

在介紹數據庫提供的各種隔離級別之前,我們先看看如果不考慮事務的隔離性,會發生的幾種問題

3.1 隔離級別引出的問題

3.1.1 臟讀

是指在沒有隔離的情況下,一個事務讀取了另外一個事務已修改但未提交(有可能回滾也有可能繼續修改)的緩沖區數據。

Spring事物基礎知識及AOP相關陷阱分析

3.1.2 不可重復讀

數據庫中的某項數據在一個事務多次讀取,但是在多次讀取期間,其他事務對其有修改并提交,導致返回值不同,這就發生了不可重復讀。

不可重復讀側重修改。

Spring事物基礎知識及AOP相關陷阱分析

3.1.3 幻讀

幻讀和不可重復讀相似。當一個事務(T1)讀取幾行記錄后(事務并沒有結束),另一個并發事務(T2)插入了一些記錄時,幻讀就發生了。在后來的查詢中,第一個事務(T1)就會發現一些原來沒有的額外記錄。

幻讀側重新增或者刪除。

Spring事物基礎知識及AOP相關陷阱分析

3.2 隔離級別

在理想狀態下,事務之間將完全隔離(即下表中的 Isolation.SERIALIZABLE ),從而可以防止這些問題發生。

然而,完全隔離會影響性能,因為隔離經常涉及到鎖定在數據庫中的記錄(甚至有時是鎖表)。

完全隔離要求事務相互等待來完成工作,會阻礙并發。因此,可以根據業務場景選擇不同的隔離級別。

 

隔離級別 含義
Isolation.DEFAULT 使用后端數據庫默認的隔離級別
Isolation.READ_UNCOMMITTED 允許讀取尚未提交的更改??赡軐е屡K讀、幻讀或不可重復讀。
Isolation.READ_COMMITTED (Oracle 默認級別)允許從已經提交的并發事務讀取??煞乐古K讀,但幻讀和不可重復讀仍可能會發生。
Isolation.REPEATABLE_READ (MYSQL默認級別)對相同字段的多次讀取的結果是一致的,除非數據被當前事務本身改變??煞乐古K讀和不可重復讀,但幻讀仍可能發生。
Isolation.SERIALIZABLE 完全服從ACID的隔離級別,確保不發生臟讀、不可重復讀和幻讀。這在所有隔離級別中也是最慢的,因為它通常是通過完全鎖定當前事務所涉及的數據表來完成的。

 

四、Spring 事務的傳播機制

Spring 事務的傳播機制描述了在嵌套事務當中,當前事務與外部事務(最近的那個,有可能沒有)的繼承關系。

比如一個事務方法里面調用了另外一個事務方法,那么兩個方法是各自作為獨立的方法提交還是內層的事務合并到外層的事務一起提交,這就是需要事務傳播機制的配置來確定怎么樣執行。

Spring 事務的傳播有如下機制

 

類型 描述
PROPAGATION_REQUIRED Spring默認的傳播機制,能滿足絕大部分業務需求,如果外層有事務,則當前事務加入到外層事務,一塊提交,一塊回滾。如果外層沒有事務,新建一個事務執行
PROPAGATION_REQUES_NEW 該事務傳播機制是每次都會新開啟一個事務,同時把外層事務掛起,當當前事務執行完畢,恢復上層事務的執行。如果外層沒有事務,執行當前新開啟的事務即可
PROPAGATION_SUPPORT 如果外層有事務,則加入外層事務,如果外層沒有事務,則直接使用非事務方式執行。完全依賴外層的事務
PROPAGATION_NOT_SUPPORT 該傳播機制不支持事務,如果外層存在事務則掛起,執行完當前代碼,則恢復外層事務,無論是否異常都不會回滾當前的代碼
PROPAGATION_NEVER 該傳播機制不支持外層事務,即如果外層有事務就拋出異常
PROPAGATION_MANDATORY 與NEVER相反,如果外層沒有事務,則拋出異常
PROPAGATION_NESTED 該傳播機制的特點是可以保存狀態保存點,當前事務回滾到某一個點,從而避免所有的嵌套事務都回滾,即各自回滾各自的,如果子事務沒有把異常吃掉,基本還是會引起全部回滾的。

 

五、Spring 事務的應用(聲明式)

Spring 聲明式事務是指依托注解 @Transactional AOP 功能,在其方法兩端添加事務的操作,實現對被注解修飾方法的增強。

5.1 事務只讀

從事務開始(時間點a)到這個事務結束的過程中,其他事務所提交的數據,該事務將看不見!(查詢中不會出現別人在時間點a之后提交的數據)。

事務只讀只適用于 當傳播機制為 PROPAGATION_REQUIRED,PROPAGATION_REQUES_NEW 的情況

5.1.1 應用場景

在諸如統計查詢、報表查詢的過程當中,需要多次查詢,為了避免在查詢過程當中對剩余查詢數據的修改,保證數據整體在某一時刻的一致性,需要使用只讀事務。

5.1.2 使用方式

@Transactional(propagation = Propagation.REQUIRES, readOnly = true)
public List<Product> findAllProducts() {
  return this.productDao.findAllProducts();
}

5.2 事務回滾

在事務注解 @Transactional 中指定了某個異常后,捕獲到事務方法拋出了該異常或者其子類異常,會造成事務回滾。默認當捕獲到方法拋出的 RuntimeException 異常后,事務就會回滾。還可以設置當出現某異常時候不回滾,即使是運行時異常

5.2.1 使用方式

// 回滾Exception類型異常
@Transactional(rollbackFor = Exception.class)
public void test1() throws Exception {
  // ..
}

// 回滾自定義類型異常
@Transactional(rollbackForClassName = "org.transaction.demo.CustomException")
public void test2() throws Exception {
  // ..
}

// 不回滾自定義類型異常
@Transactional(noRollbackFor = CustomException.class)
public void test3() throws Exception {
  // ..
}

5.3 事務超時

如果一個事務長時間占用數據庫連接,會導致服務等待從而引起服務雪崩效應,所以設置一個合理的超時時間,是必要的。默認不超時。事務超時會引起事務回滾。

事務超時只適用于 當傳播機制為 PROPAGATION_REQUIRED,PROPAGATION_REQUES_NEW 的情況

5.3.1 使用方式

//設置事務超時時間,單位秒
@Transactional(timeout = 5)
public void test() {
  // ..
}

5.4 事務傳播機制的使用方式

//每次外層事務調用都會開啟一個新事務
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void test() {
  // ..
}

5.5 事務隔離機制的使用方式

指定事務隔離機制只適用于 當傳播機制為 PROPAGATION_REQUIRED,PROPAGATION_REQUES_NEW 的情況

//設置事務隔離級別為串行
@Transactional(isolation = Isolation.SERIALIZABLE))
public void test() {
  // ..
}

 

六、Spring 聲明式事務的 AOP 陷阱

總所周知,聲明式事務依托 AOP 功能實現對事務方法的增強,而 AOP 底層則是代理,存在代理陷阱。

6.1 AOP 代理陷阱復現

  @Transactional(rollbackFor = RuntimeException.class)
  public void insertUser(User user) {
      userMapper.insertUser(user);
      throw new RuntimeException("");
  }
  
  /**
   * 內部調用新增方法
   */
  public void insertMale(User user) {
      user.setGender("male");
      this.insertUser(user);
  }

當外部方法直接調用 insertMale(user) 的時候,事務并不會生效。

6.2 原因分析

AOP使用的是動態代理的機制,它會給類生成一個代理類,事務的相關操作都在代理類上完成。內部調用使用的是實例調用,并沒有通過代理類調用方法,所以會導致事務失效。

Spring事物基礎知識及AOP相關陷阱分析

6.2.1 偽代碼

  • 代理類
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      //代理之前做增強
      System.out.println("代理之前...");
      //根據需要添加事務處理邏輯
      ...
      //調用原有方法 insertMale
      Object obj = method.invoke(object, args);
      //做增強
      System.out.println("代理之后...");
      //根據需要添加事務處理邏輯
      ...
      return obj;
  }

當執行 insertMale() 方法時,因為沒有事務注解,所以沒有添加事務處理邏輯,所以直接調用了目標類的 insertMale() 方法。

  • 目標類執行情況
  public void insertMale(User user) {
      user.setGender("male");
      //這里的 this 指向了目標類而不是代理類
      //所以及時下面的方法添加了事務注解,但是并沒有除法增強實現,事務也還是不生效的
      this.insertUser(user);
  }

6.3 解決方案

6.3.1 注入自身

利用Spring可以循環依賴來解決問題

@Service
public class TestService {
  @Autowired
  private TestService testService;

  @Transactional(rollbackFor = RuntimeException.class)
  public void insertUser(User user) {
      userMapper.insertUser(user);
      throw new RuntimeException("");
  }
  
  /**
   * 內部調用新增方法
   */
  public void insertMale(User user) {
      user.setGender("male");
      //這里使用 字段 testService 調用事務方法
      testService.insertUser(user);
  }
}

6.3.2 使用 ApplicationContext 獲取目標類

注入 Spring 上下文 ApplicationContex, 然后獲取到 目標 bean, 再調用事務方法

@Service
public class TestService {
  @Autowired
  private ApplicationContext applicationContext;

  @Transactional(rollbackFor = RuntimeException.class)
  public void insertUser(User user) {
      userMapper.insertUser(user);
      throw new RuntimeException("");
  }
  
  /**
   * 內部調用新增方法
   */
  public void insertMale(User user) {
      user.setGender("male");
      //這里使用上下文獲取目標類實例
      TestService testService = applicationContext.getBean(TestService.class);
      testService.insertUser(user);
  }
}

6.3.3 使用 AopContext

Aop 上下文采用 ThreadLocal 保存了代理對象,可以使用 Aop 上下文來進行目標方法的調用。

使用時候要在啟動類上添加 exposeProxy = true 配置

  • 配置
@SpringBootApplication
//配置:導出代理對象到AOP上下文
@EnableAspectJAutoProxy(exposeProxy = true)
public class DemoApplication {
}
  • 使用
public class TestService {

  @Transactional(rollbackFor = RuntimeException.class)
  public void insertUser(User user) {
      userMapper.insertUser(user);
      throw new RuntimeException("");
  }
  
  /**
   * 內部調用新增方法
   */
  public void insertMale(User user) {
      user.setGender("male");
      //使用AOP上下文獲取目標代理類
      TestService testService = (TestService) AopContext.currentProxy();
      testService.insertUser(user);
  }
}

到此這篇關于Spring事物基礎知識及AOP相關陷阱分析的文章就介紹到這了,更多相關Spring事物基礎 AOP陷阱內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://www.cnblogs.com/qnlcy/p/15237377.html

延伸 · 閱讀

精彩推薦
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
主站蜘蛛池模板: 在线观看的av | 成人乱人乱一区二区三区 | 国产精品一区二区不卡 | 欧美日韩国产在线播放 | 狠狠干av| 国产精品久久久久久久 | 日韩欧美在线一区 | 精品国产凹凸成av人导航 | 亚洲乱码国产乱码精品精的特点 | 黄色免费看 | 欧美在线综合 | 免费成人黄色大片 | 欧美一区二区久久 | 国精产品99永久一区一区 | 精品国产91乱码一区二区三区 | 欧美激情一区二区三区 | 看亚洲a级一级毛片 | 爱爱视频网站 | 久草观看 | 免费三片在线观看网站 | 蜜桃tv一区二区三区 | 国产精品一区二区久久 | 黄色av网站在线观看 | 日韩精品一二三区 | 91精品国产综合久久久久久漫画 | 久久精品一区二区三区四区 | 91精品久久久久久久久中文字幕 | 国色天香成人网 | 亚洲淫视频 | 日韩在线观看中文字幕 | 亚洲成人观看 | 亚洲在线一区二区 | 黄色成人一级片 | 一性一交一色生活片 | 转生成为史莱姆这档事第四季在线观看 | 午夜精品久久久久 | 激情在线视频 | av在线电影网 | 无码日韩精品一区二区免费 | 亚洲国产精品久久 | 久久一精品|