spring 自定義事件發布及監聽(簡單實例)
前言:
Spring的AppilcaitionContext能夠發布事件和註冊相對應的事件監聽器,因此,它有一套完整的事件發布和監聽機制。
流程分析:
在一個完整的事件體系中,除了事件和監聽器以外,還應該有3個概念;
1. 事件源:事件的產生者,任何一個event都必須有一個事件源;
2. 事件廣播器:它是事件和事件監聽器之間的橋梁,負責把事件通知給事件監聽器;
3. 事件監聽器註冊表:就是spring框架為所有的監聽器提供了一個存放的地方;
通過流程圖,可以看出它們是如何各司其職的,如下:
其實通過流程圖,我們很容易發現事件體系就是觀察者模式的具體實現,它並沒有任何的神秘之處。
結構分析:
1. 事件類(ApplicaitonEvent):目前spring框架本身僅僅提供了幾個事件,很多的事件都是需要自定義的。
ApplicationEvent唯一的構造函數是ApplicaitonEvent(Object source),通過source指定事件源。 它有兩個子類;
(1)ApplicationContextEvent:容器事件,也就是說事件源是ApplicationContext,框架提供了四個子類,分別代表容器啟動,刷新,停止和關閉事件。
(2)RequestHandleEvent:這是一個與Web應用相關的事件,當一個請求被處理後,才會產生該事件。
一般來說,我們都是擴展ApplicationEvent來自定義事件。下面會有栗子。
2. 事件監聽器接口(ApplicationListener)
所有的監聽器都需要實現該接口,該接口只定義了一個方法:onApplicaitonEvent (E event),該方法接收事件對象,在該方法中編寫事件的響應處理邏輯。
實例分析:
通過一個實例來講解事件發布和事件監聽的過程。這個例子包括一個模擬的郵件發送器MailSender,它在向目的地發送郵件的時候 會產生一個MailSendEvent事件,我們同時向容器中註冊了該事件的監聽器MailSendListener;
上代碼:MailSendEvent
/** * 繼承了ApplicationContextEvent,就是個容器事件*/ public class MailSendEvent extends ApplicationContextEvent { private String to; //目的地 public MailSendEvent(ApplicationContext source, String to) { super(source); this.to = to; } public String getTo(){ return this.to; } }
很明顯,這裏的source是ApplicationContext容器。
我們再定義一個該事件的監聽器MailSendListener,如下
@Component public class MailSendListener implements ApplicationListener<MailSendEvent>{ @Override public void onApplicationEvent(MailSendEvent mailSendEvent) { MailSendEvent event = mailSendEvent; System.out.println("MailSender向"+ event.getTo()+ "發送了郵件"); } }
上述提及到所有的監聽器都必須要實現ApplicationListener,這裏是個泛型類,指定了該監聽器只監聽MailSendEvent事件。
OK,那我們現在來觸發事件:MailSender,也就是事件源
@Component("mailSender") public class MailSender { @Autowired private ApplicationContext applicationContext; //容器事件由容器觸發 public void sendMail(String to){ System.out.println("MailSender開始發送郵件"); MailSendEvent event = new MailSendEvent(applicationContext,to); applicationContext.publishEvent(event); } }
最後寫個測試類,容器啟動:
public class SpringEventTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("web/WEB-INF/applicationContext.xml"); MailSender sender = (MailSender)context.getBean("mailSender"); sender.sendMail("北京"); } }
記得在applicationContext.xml裏面加上註解掃描啊,我這裏都是放在springEvent包裏的,所以加上 <context:component-scan base-package="springEvent"/>
好了,啟動容器,發送郵件:執行結果如下
spring 自定義事件發布及監聽(簡單實例)