一、Spring事件監聽介紹 Spring對事件監聽是通過事件類型、事件類型監聽和事件發佈器3個部分來完成的 // 1. 自定義訂單事件 public class OrderEvent extends ApplicationEvent { ... } // 2. 定義訂單監聽器 @Component ...
一、Spring事件監聽介紹
Spring對事件監聽是通過事件類型、事件類型監聽和事件發佈器3個部分來完成的
// 1. 自定義訂單事件
public class OrderEvent extends ApplicationEvent {
...
}
// 2. 定義訂單監聽器
@Component
public class OrderListener implements ApplicationListener<OrderEvent> {
@Override
public void onApplicationEvent(OrderEvent event) {
// 生成訂單、刪除購物車、扣減庫存
```
}
}
// 3. 通過applicationEventPublisher發佈事件
@Resource
private ApplicationEventPublisher applicationEventPublisher;
private void saveOrder(MallUserVO mallUserVO, Long couponUserId, List<ShopCatVO> shopcatVOList, String orderNo) {
// 訂單檢查
```
// 生成訂單號
String orderNo = NumberUtil.genOrderNo();
// 發佈訂單事件,在事件監聽中處理下單邏輯
applicationEventPublisher.publishEvent(new OrderEvent(orderNo, mallUserVO, couponUserId, shopcatVOList));
// 所有操作成功後,將訂單號返回
return orderNo;
```
}
上面的代碼已經是將訂單的保存邏輯從下單介面解耦到訂單監聽器中了,但是Spring使用預設自帶的SimpleApplicationEventMulticaster
事件監聽發佈類是同步通知事件監聽器的,這裡會阻塞下單主線程,影響介面響應時長。
二、使用非同步的事件監聽發佈類
由於預設的
SimpleApplicationEventMulticaster
類是同步調用,這裡可以從2個方面入手:
- 從事件監聽器:將事件監聽器的事件觸發方法改為非同步執行,例如加入將生成訂單、刪除購物車、扣減庫存邏輯放入線程池,或者是在
onApplicationEvent
放上上加上@Async
註解,表示該方法非同步執行。- 通過修改預設事件監聽發佈類的
taskExecutor
屬性,這樣可以使用已有的件監聽發佈類來優化相關邏輯
/**
* 系統啟動時執行
*/
@Component
public class SpringBeanStartupRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
// 設置spring預設的事件監聽為非同步執行
SimpleApplicationEventMulticaster multicaster = SpringContextUtil.getBean(SimpleApplicationEventMulticaster.class);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
5,
10,
60L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(500),
new CustomizableThreadFactory("newbee—event-task"),
new ThreadPoolExecutor.CallerRunsPolicy()
);
multicaster.setTaskExecutor(threadPoolExecutor);
}
}
在系統啟動時反射修改
SimpleApplicationEventMulticaster
類的taskExecutor
屬性,從而讓SimpleApplicationEventMulticaster
類支持非同步事件通知
三、事件監聽機制的代碼思考
通過事件監聽機制,我們將下單邏輯拆分成如下步驟:
- 訂單檢查
- 生成訂單號
- 發佈訂單事件,在事件監聽中處理訂單保存邏輯
- 所有操作成功後,將訂單號返回
每個步驟都是各自獨立不互相影響,後期引入消息隊列,對代碼的改動也是很少,只需將事件發佈和事件監聽的代碼換成消息隊列的消息發送和消息監聽即可。