JDK事件java
java經過java.util.EventObject類和java.util.EventListener接口描述事件和監聽器web
事件源,事件的產生者,任何一個EventObject都必須擁有一個事件源。
事件監聽器註冊表,保存事件監聽器的地方。
事件廣播器,把事件通知給事件監聽器。
事件源、事件監聽器註冊表和事件廣播這3個角色有時能夠由同一個對象承擔,如java.swing包中的JButton、JCheckBox等組件,它們分別集以上3個角色於一身。spring
事件體系是觀察者模式的一種具體實現方式app
Spring 事件ide
Spring的ApplicationContext可以發佈事件而且容許註冊相應的事件監聽器post
Spring事件類ApplicationEventthis
// 繼承了JDK的EventObject public abstract class ApplicationEvent extends EventObject { // 惟一的構造方法,source指定事件源 public ApplicationEvent(Object source) { super(source); this.timestamp = System.currentTimeMillis(); } }
Spring事件類ApplicationEvent有兩個子類ApplicationContextEvent、RequestHandledEventspa
// 容器事件類 public abstract class ApplicationContextEvent extends ApplicationEvent {} // 與web應用相關的事件RequestHandledEvent,當一個Http請求被處理後,產生該事件 public class RequestHandledEvent extends ApplicationEvent {}
ApplicationContextEvent有4個子類ContextClosedEvent、ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent,分別表示容器啓動、刷新、中止及關閉的事件。code
RequestHandledEvent只有定義了DispatcherServlet時纔會產生該事件,它的子類ServletRequestHandledEvent表明Servlet請求事件。xml
spring事件監聽器
// 繼承了JDK的EventListener接口 // E extends ApplicationEvent是一個泛型 public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { // 只定義了一個方法 void onApplicationEvent(E event); }
ApplicationListener有兩個子類GenericApplicationListener、SmartApplicationListener
public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered { /** * 指定監聽器支持哪一種類型的容器事件 */ boolean supportsEventType(Class<? extends ApplicationEvent> eventType); /** * 指定監聽器僅對何種事件源對象作出響應 */ boolean supportsSourceType(Class<?> sourceType); } public interface GenericApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered { /** * 指定監聽器對何種事件類型作出響應 */ boolean supportsEventType(ResolvableType eventType); /** * 指定監聽器對何種事件源作出響應 */ boolean supportsSourceType(Class<?> sourceType); }
spring事件廣播器
public interface ApplicationEventMulticaster {}
ApplicationEventMulticaster有兩個子類AbstractApplicationEventMulticaster、SimpleApplicationEventMulticaster
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {} public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {}
AbstractApplicationContext
AbstractApplicationContext有一個成員變量applicationEventMulticaster,這個成員變量提供了容器監聽器的註冊表
AbstractApplicationContext的refresh方法
postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); initMessageSource(); /* * 初始化應用上下文事件廣播器 * 能夠自定義事件廣播器,實現ApplicationEventMulticaster便可, * 若是沒有找到自定義的廣播器,自動使用SimpleApplicationEventMulticaster做爲事件廣播器 */ initApplicationEventMulticaster(); onRefresh(); /* * 註冊事件監聽器 * 根據反射機制,從BeanDefinitionRegistry中找出全部實現了ApplicationListener的Bean, * 並註冊 */ registerListeners(); finishBeanFactoryInitialization(beanFactory); // 容器啓動完成,向容器中的全部監聽器發佈事件 finishRefresh();
demo
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.16.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.16.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.3.16.RELEASE</version> </dependency>
package test; import org.springframework.context.ApplicationContext; import org.springframework.context.event.ApplicationContextEvent; /** * 自定義的郵件發送事件類,繼承自ApplicationContextEvent */ public class MailSendEvent extends ApplicationContextEvent { private String to; // 事件源source是ApplicationContext public MailSendEvent(ApplicationContext source, String to) { super(source); this.to = to; } public String getTo() { return this.to; } }
package test; import org.springframework.context.ApplicationListener; /** * 自定義的郵件發送事件監聽器,繼承自ApplicationListener */ public class MailSendListener implements ApplicationListener<MailSendEvent>{ // 接收到事件後的處理邏輯 public void onApplicationEvent(MailSendEvent event) { MailSendEvent mse = (MailSendEvent) event; System.out.println("MailSendListener:向" + mse.getTo() + "發送完一封郵件"); } }
package test; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class MailSender implements ApplicationContextAware { private ApplicationContext ctx ; // 實現了ApplicationContextAware,在bean的生命週期會自動調用這個方法 public void setApplicationContext(ApplicationContext ctx) throws BeansException { this.ctx = ctx; } public void sendMail(String to){ // 發送郵件 System.out.println("MailSender:模擬發送郵件..."); // 建立事件 MailSendEvent mse = new MailSendEvent(this.ctx,to); // 發佈事件 ctx.publishEvent(mse); } }
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:c="http://www.springframework.org/schema/c" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="sender" class="test.MailSender"/> <bean id="sendListener" class="test.MailSendListener"/> </beans>
package test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Driver { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("my.xml"); MailSender mailSender = ctx.getBean(MailSender.class); mailSender.sendMail("test mail."); System.out.println("done."); } }