中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot如何實現異步事件驅動

發布時間:2021-06-28 14:18:59 來源:億速云 閱讀:164 作者:小新 欄目:開發技術

這篇文章將為大家詳細講解有關SpringBoot如何實現異步事件驅動,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

在項目實際開發過程中,我們有很多這樣的業務場景:一個事務中處理完一個業務邏輯后需要跟著處理另外一個業務邏輯,偽碼大致如下:

@Service
public class ProductServiceImpl {
 ...
    public void saveProduct(Product product) {
        productMapper.saveOrder(product);
        notifyService.notify(product);
    }
 ...
}

很簡單并且很常見的一段業務邏輯:首先將產品先保存數據庫,然后發送通知。

某一天你們可能需要把新增的產品存到Es中,這時候也需要代碼可能變成這樣:

@Service
public class ProductServiceImpl {
 ...
    public void saveProduct(Product product) {
        productMapper.saveProduct(product);
        esService.saveProduct(product)
        notifyService.notify(product);
    }
 ...
}

隨著業務需求的變化,代碼也需要跟著一遍遍的修改。而且還會存在另外一個問題,如果通知系統掛了,那就不能再新增產品了。

對于上面這種情況非常適合引入消息中間件(消息隊列)來對業務進行解耦,但并非所有的業務系統都會引入消息中間件(引入會第三方架構組件會帶來很大的運維成本)。

Spring提供了事件驅動機制可以幫助我們實現這一需求。

Spring事件驅動

spring事件驅動由3個部分組成

  • ApplicationEvent:表示事件本身,自定義事件需要繼承該類,用來定義事件

  • ApplicationEventPublisher:事件發送器,主要用來發布事件

  • ApplicationListener:事件監聽器接口,監聽類實現ApplicationListener 里onApplicationEvent方法即可,也可以在方法上增加@EventListener以實現事件監聽。

實現Spring事件驅動一般只需要三步:

  • 自定義需要發布的事件類,需要繼承ApplicationEvent類

  • 使用ApplicationEventPublisher來發布自定義事件

  • 使用@EventListener來監聽事件

這里需要特別注意一點,默認情況下事件是同步的。即事件被publish后會等待Listener的處理。如果發布事件處的業務存在事務,監聽器處理也會在相同的事務中。如果需要異步處理事件,可以onApplicationEvent方法上加@Aync支持異步或在有@EventListener的注解方法上加上@Aync。

源碼實戰

創建事件

public class ProductEvent extends ApplicationEvent {
    public ProductEvent(Product product) {
        super(product);
    }
}

發布事件

@Service
public class ProductServiceImpl implements IproductService {
 ...
    @Autowired
    private ApplicationEventPublisher publisher;
 
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveProduct(Product product) {
  productMapper.saveProduct(product); 
        //事件發布
        publisher.publishEvent(product);
    }
    ...
}

事件監聽

@Slf4j
@AllArgsConstructor
public class ProductListener {

 private final NotifyService notifyServcie;

 @Async
 @Order
 @EventListener(ProductEvent.class)
 public void notify(ProductEvent event) {
  Product product = (Product) event.getSource();
  notifyServcie.notify(product, "product");
 }
}

在SpringBoot啟動類上增加@EnableAsync 注解

@Slf4j
@EnableSwagger2
@SpringBootApplication
@EnableAsync
public class ApplicationBootstrap {
...
}

使用了Async后會使用默認的線程池SimpleAsyncTaskExecutor,一般我們會在項目中自定義一個線程池。

@Configuration
public class ExecutorConfig {
    /** 核心線程數 */
    private int corePoolSize = 10;
    /** 最大線程數  */
    private int maxPoolSize = 50;
    /** 隊列大小  */
    private int queueCapacity = 10;
    /** 線程最大空閑時間   */
    private int keepAliveSeconds = 150;

    @Bean("customExecutor")
    public Executor myExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setThreadNamePrefix("customExecutor-");
        executor.setKeepAliveSeconds(keepAliveSeconds);

        // rejection-policy:當pool已經達到max size的時候,如何處理新任務
        // CALLER_RUNS:不在新線程中執行任務,而是由調用者所在的線程來執行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

關于“SpringBoot如何實現異步事件驅動”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

象州县| 凉城县| 台北县| 昌黎县| 墨竹工卡县| 花垣县| 罗城| 朔州市| 大化| 安化县| 新源县| 石阡县| 苗栗市| 嫩江县| 玉树县| 无棣县| 秭归县| 绵竹市| 镇原县| 富平县| 赞皇县| 汤原县| 淮安市| 黄冈市| 台江县| 佛学| 富川| 平江县| 汕头市| 邹平县| 苍梧县| 云龙县| 赞皇县| 建瓯市| 连州市| 闸北区| 萍乡市| 灵石县| 凤台县| 镇雄县| 深州市|