前言:web
Spring的AppilcaitionContext可以發佈事件和註冊相對應的事件監聽器,所以,它有一套完整的事件發佈和監聽機制。spring
流程分析:app
在一個完整的事件體系中,除了事件和監聽器之外,還應該有3個概念;框架
1. 事件源:事件的產生者,任何一個event都必須有一個事件源;ide
2. 事件廣播器:它是事件和事件監聽器之間的橋樑,負責把事件通知給事件監聽器;函數
3. 事件監聽器註冊表:就是spring框架爲全部的監聽器提供了一個存放的地方;測試
經過流程圖,能夠看出它們是如何各司其職的,以下:this
其實經過流程圖,咱們很容易發現事件體系就是觀察者模式的具體實現,它並無任何的神祕之處。spa
結構分析:code
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"/>
好了,啓動容器,發送郵件:執行結果以下