1. 程式人生 > 其它 >SpringBoot 註解@Async不生效的解決方法【非同步處理】

SpringBoot 註解@Async不生效的解決方法【非同步處理】

由於工作需求,邏輯需要非同步處理,測試過程中發現非同步不生效,請求示例和響應結果展示如下:

響應結果:

 根據測試用例會發現:執行緒ID一樣,方法 syncData() 和主方法同步執行,非同步不生效!

解決方案一

同一個類中呼叫需要先獲取代理物件,也就是手動獲取物件
@ResponseBody
@RequestMapping(path = "/testAsync", method = RequestMethod.GET)
public String testAsync() throws InterruptedException {
    System.out.println("主方法執行開始......" + Thread.currentThread().getId());
    // 手動獲取代理物件
    SpringUtil.getApplicationContext().getBean(ExpenseApplicationCallback.class).syncData();
    System.out.println("主方法執行結束......" + Thread.currentThread().getId());
    return "測試非同步完成";
}

@Async
public void syncData() throws InterruptedException {
    System.out.println("非同步方法執行開始......" + Thread.currentThread().getId());
    Thread.sleep(3000);
    System.out.println("非同步方法執行結束......" + Thread.currentThread().getId());
}

 執行結果:

  

 解決方案二

不同的類呼叫,直接注入即可
@ResponseBody
@RequestMapping(path = "/testAsync", method = RequestMethod.GET)
public String testAsync() throws InterruptedException {
    System.out.println("主方法執行開始......" + Thread.currentThread().getId());
    // 不同的類直接呼叫
    expenseApplicationDataService.syncData();
    System.out.println("主方法執行結束......" + Thread.currentThread().getId());
    return "測試非同步完成";
}


ExpenseApplicationDataService.java
@Async
public void syncData() throws InterruptedException {
    System.out.println("非同步方法執行開始......" + Thread.currentThread().getId());
    Thread.sleep(3000);
    System.out.println("非同步方法執行結束......" + Thread.currentThread().getId());
}

執行結果:

  

實踐總結 

1、在需要用到的 @Async 註解的類上加上 @EnableAsync,或者直接加在springboot啟動類上;
2、非同步處理方法(也就是加了 @Async 註解的方法)只能返回的是 void 或者 Future 型別;
3、同一個類中呼叫非同步方法需要先獲取代理類,因為 @Async 註解是基於Spring AOP (面向切面程式設計)的,而AOP的實現是基於動態代理模式實現的。有可能因為呼叫方法的是物件本身而不是代理物件,因為沒有經過Spring容器。。。。。。這點很重要,也是經常遇到的