終於可以愉快的擼Java異步代碼了!

  異步響應式編程可以極大的提高系統的併發呑吐量,但由於Java沒有類似於其他語言的Async/Await機制,所以只能通過CompletableFuture.thenXXX()來串聯各個異步任務,這給習慣了寫同步增刪改查的小夥伴們帶來了些小麻煩。如果說C#基於狀態機在編譯時實現了await轉換,那麼Java肯定也可以基於相同的原理實現await,作者上網一搜果然找到了ea-async,使用與C#相同的方式實現了await異步方法,這回終於可以愉快的擼Java異步代碼了。

一、 示例代碼

  舉個扣減庫存並保存訂單的例子,在沒有await方式下的示例代碼如下:

public CompletableFuture<?> saveOrder(Order order) {
    //1.開始事務
    return DataStore.DemoDB.beginTransaction().thenCompose(txn -> {
        //2.扣庫存
        var cmd = new SqlUpdateCommand<Order>();
        cmd.update(e -> e.Stock = e.Stock - order.Quantity); //當前量扣除訂單量
        cmd.where(e -> e.ProductId == order.ProductId);
        var outs = cmd.output(e -> e.Stock);
        return cmd.execAsync(txn).thenCompose(rows -> {
            //3.判斷庫存
            if (rows == 0 || outs.get(0) < 0) 
                return CompletableFuture.failedFuture("庫存不足");
            //4.保存訂單
            return order.saveAsync(txn);
        }).thenCompose(r -> txn.commitAsync()); //5.遞交事務
    }).thenApply(r -> "Done.");
}

  WTF! 一層套一層的回調,這還只是個簡單的例子啊。但是如果使用await的方式,業務邏輯就變得清爽多了:

import static sys.Async.await;

public CompletableFuture<?> saveOrder(Order order) {
    //1.開始事務
    var txn = await(DataStore.DemoDB.beginTransaction());
    //2.扣庫存
    var cmd = new SqlUpdateCommand<Order>();
    cmd.update(e -> e.Stock = e.Stock - order.Quantity); //當前量扣除訂單量
    cmd.where(e -> e.ProductId == order.ProductId);
    var outs = cmd.output(e -> e.Stock); 
    var rows = await(cmd.execAsync(txn));
    //3.判斷庫存
    if (rows == 0 || outs.get(0) < 0)
        return CompletableFuture.failedFuture("庫存不足");
    //4.保存訂單
    await(order.saveAsync(txn));
    //5.遞交事務
    await(txn.commitAsync());
    return CompletableFuture.completedFuture("Done.");
}

二、 實現原理

  核心思想沒有變,還是代碼分析轉換。作者原本想利用JDT在源碼層進行await轉換,但是工作量還是比較大的,在這裏感謝github/ea-async項目,使得作者只修改了十幾行代碼就實現了上述效果,具體轉換過程如下:

  1. 服務模型的虛擬代碼經過JDT分析、轉換、編譯爲class文件(參考前篇說明);
  2. 調用ea-async的Transformer類直接分析與轉換class文件內的await方法調用,生成新的class文件。

具體參考源碼PublishService的compileService()及transformAsync()方法。

三、 本篇小結

  先解釋一下上篇"優雅的Java ORM"小夥伴們的評論,有說這麼多ORM幹嗎還要造一個的,也有說不夠"優雅"的,其實造輪子最根本的原因是:異步支持!,Spring WebFlux及VertX有相應的異步操作數據庫的支持,但本框架沒法集成。MyBatis之類的全是同步操作,小的應用系統沒有問題,高併發系統的呑吐量就非常可憐了,這個大家可以測一下Spring MVC與WebFlux的性能對比。

  軟件技術日新月異,新一代的開發框架必定是異步的!對於作者來講Spring還不夠簡單優雅,運行的也不夠快,所以纔會嘗試重新造這個大輪子,爭取讓應用系統的開發人員有更多的時間關注數據結構、業務邏輯和用戶體驗,也爭取讓小夥伴們有一個絲般順滑的開發體驗。

邊碼代碼邊碼文實屬不易,作者需要您的支持請您多多點贊推薦!另歡迎感興趣的小夥伴加入我們!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章