文章連接:https://liuyueyi.github.io/hexblog/hexblog/2018/06/09/180609-Spring之事件驅動機制的簡單使用/java
關於事件的發起與相應,在客戶端的交互中可算是很是頻繁的事情了,關於事件的發佈訂閱,在Java生態中,EventBus可謂是很是有名了,而Spring也提供了事件機制,本文則主要介紹後端如何在Spring的環境中,使用事件機制git
主要藉助org.springframework.context.ApplicationEventPublisher#publishEvent(org.springframework.context.ApplicationEvent)
來發布事件,而接受方,則直接在處理的方法上,添加 @@EventListener
註解便可github
發佈一個事件,因此第一件事就是要定義一個事件,對Spring而言,要求自定義的事件繼承自ApplicationEvent
類, 一個簡單的demo以下spring
public class NotifyEvent extends ApplicationEvent { @Getter private String msg; public NotifyEvent(Object source, String msg) { super(source); this.msg = msg; } }
發佈時間則比較簡單,直接拿到ApplicationContext實例,執行publish方法便可,以下面給出一個簡單的發佈類後端
@Component public class NotifyPublisher implements ApplicationContextAware { private ApplicationContext apc; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.apc = applicationContext; } // 發佈一個消息 public void publishEvent(int status, String msg) { if (status == 0) { apc.publishEvent(new NotifyEvent(this, msg)); } else { apc.publishEvent(new NewNotifyEvent(this, msg, ((int) System.currentTimeMillis() / 1000))); } } }
在方法上添加註解便可,以下app
@Component public class NotifyQueueListener { @EventListener public void consumerA(NotifyEvent notifyEvent) { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("A: " + Thread.currentThread().getName() + " | " + notifyEvent.getMsg()); } @EventListener public void consumerB(NewNotifyEvent notifyEvent) { System.out.println("B: " + Thread.currentThread().getName() + " | " + notifyEvent.getMsg()); } @EventListener public void consumerC(NotifyEvent notifyEvent) { System.out.println("C: " + Thread.currentThread().getName() + " | " + notifyEvent.getMsg()); } }
上面給出了使用的姿式,看起來並不複雜,也比較容易使用,可是一個問題須要在使用以前弄明白了,發佈事件和監聽器是怎麼關聯起來的呢?異步
那麼若是發佈者,推送的是一個NotifyEvent
類型的事件,那麼接收者是怎樣的呢?ide
測試用例以下:學習
NewNotifyEvent
繼承自上面的NotifyEvent
測試
public class NewNotifyEvent extends NotifyEvent { @Getter private int version; public NewNotifyEvent(Object source, String msg) { super(source, msg); } public NewNotifyEvent(Object source, String msg, int version) { super(source, msg); this.version = version; } }
而後藉助上面的消息發佈者發送一個消息
@Test public void testPublishEvent() throws InterruptedException { notifyPublisher.publishEvent(1, "新的發佈事件! NewNotify"); System.out.println("---------"); notifyPublisher.publishEvent(0, "舊的發佈事件! Notify"); }
輸出結果以下,對於NewNotifyEvent, 參數類型爲NotifyEvent的consumerA, consumerC均可以接收到
A: main | 新的發佈事件! NewNotify C: main | 新的發佈事件! NewNotify B: main | 新的發佈事件! NewNotify --------- A: main | 舊的發佈事件! Notify C: main | 舊的發佈事件! Notify
上面消息處理是串行的,那麼前後順序怎麼肯定? (下面的答案不肯定,有待深刻源碼驗證!!!)
對於異步消費,即在消費者方法上添加一個@Async
註解,並須要在配置文件中,開啓異步支持
@Async @EventListener public void processNewNotifyEvent(NewNotifyEvent newNotifyEvent) { System.out.println("new notifyevent: " + newNotifyEvent.getMsg() + " : " + newNotifyEvent.getVersion()); }
配置支持
@Configuration @EnableAsync public class AysncListenerConfig implements AsyncConfigurer { /** * 獲取異步線程池執行對象 * * @return */ @Override public Executor getAsyncExecutor() { return new ThreadPoolExecutor(5, 10, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(), new DefaultThreadFactory("test"), new ThreadPoolExecutor.CallerRunsPolicy()); } }
一灰灰的我的博客,記錄全部學習和工做中的博文,歡迎你們前去逛逛
盡信書則不如,已上內容,純屬一家之言,因我的能力有限,不免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激