spring學習筆記(16)趣談spring 事件機制[2]:多監聽器流水線式順序處理


上一篇我們使用到的ApplicationListener是無序的,結合異步調度它能滿足了我們的大部分應用場景,但現在我們來個另類的需求,我們來模擬一條作業調度流水線,它不能異步,必須按照先后次序執行不同的任務才能得到我們的最終結果。
需求示例:現在假如華中科技大學的小白想要為它的智能機器人作品申報國家創新獎,需要經過學校、省級創新科研機構、國家創新科研機構逐層審核。我們嘗試通過事件來實現,核心就在監聽器實現SmartApplicationListener接口。示例如下:

1. 配置事件發布者小白:

public class XiaoBai implements ApplicationContextAware {

private ApplicationContext applicationContext;//底層事件發布者

public void reportWorks(){//申報作品
AuditEvent auditEvent = new AuditEvent(this);
applicationContext.publishEvent(auditEvent);
//小白獲取期待已久的最終結果
System.out.println("最終審核結果:" + auditEvent.getStatus() + "——" + auditEvent.getAdvice());
}

@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
}

關於上述配置可參考我的上一篇文章《spring學習筆記(13)趣談spring 事件:實現業務邏輯解耦,異步調用提升用戶體驗》

2. 配置審核事件源

public class AuditEvent extends ApplicationEvent {

private Boolean status ; //當前申報狀態
private String work;//申報作品
private String advice;//當前申報意見


public AuditEvent(Object source) {
super(source);
status = true;//初始窗台
advice = "尚未審核";
}
//ignore getter and setter
}

3. 配置事件監聽器

我們實現需求的核心部分來了,先上代碼

/******************學校審核監聽器******************/
public class SchoolListener implements SmartApplicationListener {

@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("獲取當前的申報狀態為:"+((AuditEvent)event).getStatus() + "——" + ((AuditEvent)event).getAdvice());
((AuditEvent)event).setStatus(true);
((AuditEvent)event).setAdvice("學校審核意見:有創意,非常棒!");
}

@Override
public int getOrder() {
return 1;//獲取學校監聽(審核)的優先級
}

@Override//這是我們的監聽器智能所在之一,能夠根據事件類型動態監聽
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return eventType == AuditEvent.class;
}

@Override//這是我們的監聽器智能所在之二,能夠根據事件發布者類型動態監聽
public boolean supportsSourceType(Class<?> sourceType) {
return sourceType == XiaoBai.class;
}
}
/******************省級審核監聽器******************/
public class ProvinceListener implements SmartApplicationListener {

@Override
public void onApplicationEvent(ApplicationEvent event) {
if(((AuditEvent)event).getStatus()){//如果上層審核通過
System.out.println("獲取當前的申報狀態為:"+((AuditEvent)event).getStatus() + "——" + ((AuditEvent)event).getAdvice());
((AuditEvent)event).setStatus(true);
((AuditEvent)event).setAdvice("省級審核意見:還行,通過吧!");
}
}

@Override
public int getOrder() {
return 2;
}

@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return eventType == AuditEvent.class;
}

@Override
public boolean supportsSourceType(Class<?> sourceType) {
return sourceType == XiaoBai.class;
}

}

/******************國家級審核監聽器******************/
public class CountryListener implements SmartApplicationListener {

@Override
public void onApplicationEvent(ApplicationEvent event) {
if(((AuditEvent)event).getStatus()){//如果上層審核通過
System.out.println("獲取當前的申報狀態為:"+((AuditEvent)event).getStatus() + "——" + ((AuditEvent)event).getAdvice());
((AuditEvent)event).setStatus(true);
((AuditEvent)event).setAdvice("國家審核意見:一般般,勉強通過吧!");
}
}

@Override
public int getOrder() {
return 3;
}

@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return eventType == AuditEvent.class;
}

@Override
public boolean supportsSourceType(Class<?> sourceType) {
return sourceType == XiaoBai.class;
}

}

在這里,我們的實例為了方便演示而簡化配置。我們的發布源支持類型是小白,根據更實際的需求,我們可以讓小白繼承Student類,然后讓sourceType只要是Student的子類即可,這樣就能滿足任何繼承了Student的學生都能申報了。
在實現了SmartApplicationListener的監聽器中,我們通過重寫GetOrder方法來修改不同監聽器的順序,優先級越小,則越先被調用。通過配置不同的優先級,且讓監聽器之間阻塞調用。我們就能實現流水線式的有序事件調用,這在實際應用場景中還是蠻有意義的

5. 在IOC容器中注冊監聽器

<bean id="schoolListener" class="test.event2.SchoolListener" />
<bean id="provinceListener" class="test.event2.ProvinceListener" />
<bean id="countryListener" class="test.event2.CountryListener" />

<bean id="xiaoBai" class="test.event2.XiaoBai" /><!-- 測試時注入使用 -->

6. 測試方法

public class MainTest {
public static void main(String args[]) throws InterruptedException{
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:test/event2/event.xml");
XiaoBai xiaobai = (XiaoBai) ac.getBean("xiaoBai");
xiaobai.reportWorks();//小白要開始申報項目啦
}
}

調用測試代碼,我們得到運行結果:
獲取當前的申報狀態為:true——尚未審核
獲取當前的申報狀態為:true——學校審核意見:有創意,非常棒!
獲取當前的申報狀態為:true——省級審核意見:還行,通過吧!
最終審核結果:true——國家審核意見:一般般,勉強通過吧!

於是,小白的作品終於評上了國家創新科技獎了,這讓他高興了好一陣子。

源碼下載

本實例源碼可到我的github倉庫https://github.com/jeanhao/spring下的event2文件夾下載


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com