Spring的event的自帶執行緒池,在執行過程中,發生異常事務會回滾嗎
阿新 • • 發佈:2020-12-27
技術標籤:Spring執行緒池事務回滾執行緒池與事務Spring
背景
- 推薦閱讀Spring的event的基本使用過程與理解
- 測試當執行緒池中的任務發生異常(RuntimeException)不捕獲與@Transactional關係
過程
- 測試事務(入口處沒有註解@Transactional)
- 測試邏輯。業務邏輯程式碼先執行了資料庫的更新操作,後續邏輯發生空指標異常。
- 資料庫情況
- 程式碼情況
監聽程式碼情況
@EventListener
@Async("AsyncTaskExecutor")
public void handleMyEvent(MyEvent myEvent) {
System.out.println("執行緒:" + Thread.currentThread().getName() + "執行了MyEvent事件");
// 具體的業務邏輯過程
this.eventService.handleEvent(myEvent.getAddr(), myEvent.getTime(), myEvent.getOperator());
}
具體業務邏輯程式碼。
studentService.selectByName()和studentService.update()都添加了@Transactional註解。異常是RuntimeException,因此Spring是能夠感知到的。
@Override
public void handleEvent(String addr, Date time, String operator) {
System.out.println("event: 模擬具體的業務邏輯處理過程, 這裡單純地打印出來即可");
System.out.println("myEvent.addr: " + addr);
System.out.println("myEvent.time: " + time);
System.out. println("myEvent.operator: " + operator);
Student sara = studentService.selectByName("sara");
sara.setName("Ted");
studentService.update(sara);
String str = null;
System.out.println(str.equals("null"));
}
- 測試結果(未回滾,資料被修改 了)
- 測試事務(入口處有註解@Transactional),其他為原來初始情況。
監聽程式碼
@EventListener
@Async("AsyncTaskExecutor")
@Transactional
public void handleMyEvent(MyEvent myEvent) {
System.out.println("執行緒:" + Thread.currentThread().getName() + "執行了MyEvent事件");
// 具體的業務邏輯過程
this.eventService.handleEvent(myEvent.getAddr(), myEvent.getTime(), myEvent.getOperator());
}
測試結果(回滾了,沒有修改成功)
- 測試事務(入口處沒有註解@Transactional,業務邏輯入口處有@Transactional ),其他為原來初始情況。
@EventListener
@Async("AsyncTaskExecutor")
public void handleMyEvent(MyEvent myEvent) {
System.out.println("執行緒:" + Thread.currentThread().getName() + "執行了MyEvent事件");
// 具體的業務邏輯過程
this.eventService.handleEvent(myEvent.getAddr(), myEvent.getTime(), myEvent.getOperator());
}
@Override
@Transactional
public void handleEvent(String addr, Date time, String operator) {
System.out.println("event: 模擬具體的業務邏輯處理過程, 這裡單純地打印出來即可");
System.out.println("myEvent.addr: " + addr);
System.out.println("myEvent.time: " + time);
System.out.println("myEvent.operator: " + operator);
Student sara = studentService.selectByName("sara");
System.out.println(sara.getName());
sara.setName("Ted");
studentService.update(sara);
String str = null;
System.out.println(str.equals("null"));
}
測試結果(事務回滾)
- 測試事務(入口處有註解@Transactional,業務邏輯入口處有@Transactional ,studentService.update(sara)@Transactional去掉)。
@EventListener
@Async("AsyncTaskExecutor")
public void handleMyEvent(MyEvent myEvent) {
System.out.println("執行緒:" + Thread.currentThread().getName() + "執行了MyEvent事件");
// 具體的業務邏輯過程
this.eventService.handleEvent(myEvent.getAddr(), myEvent.getTime(), myEvent.getOperator());
}
@Override
@Transactional
public void handleEvent(String addr, Date time, String operator) {
System.out.println("event: 模擬具體的業務邏輯處理過程, 這裡單純地打印出來即可");
System.out.println("myEvent.addr: " + addr);
System.out.println("myEvent.time: " + time);
System.out.println("myEvent.operator: " + operator);
Student sara = studentService.selectByName("sara");
System.out.println(sara.getName());
sara.setName("Ted");
// 此方法沒有@Transactional
studentService.update(sara);
String str = null;
System.out.println(str.equals("null"));
}
測試結果(事務回滾)
小結
- Spring的執行緒池用在Event中,如果執行緒池中的執行緒在處理業務邏輯的過程中,發生了RuntimeExcepion時,與Spring註解@Transactional用在的哪個層級,然後導致事務會回滾,有非常大的關係。這個demo實驗有很好的參考價值。
- 注意@Transactional預設回滾的異常級別是RuntimeExcepion,而不是Excption
- @Transactional。Spring預設的傳播行為REQUIRED,業務方法需要在一個事務中執行,如果方法執行時,已處在一個事務中,那麼就加入該事務,否則自己建立一個新的事務。