JDK事件
java通过java.util.EventObject类和java.util.EventListener接口描述事件和监听器
事件源,事件的产生者,任何一个EventObject都必须拥有一个事件源。
事件监听器注册表,保存事件监听器的地方。事件广播器,把事件通知给事件监听器。事件源、事件监听器注册表和事件广播这3个角色有时可以由同一个对象承担,如java.swing包中的JButton、JCheckBox等组件,它们分别集以上3个角色于一身。事件体系是观察者模式的一种具体实现方式
Spring 事件
Spring的ApplicationContext能够发布事件并且允许注册相应的事件监听器
Spring事件类ApplicationEvent
// 继承了JDK的EventObjectpublic abstract class ApplicationEvent extends EventObject { // 唯一的构造方法,source指定事件源 public ApplicationEvent(Object source) { super(source); this.timestamp = System.currentTimeMillis(); }}
Spring事件类ApplicationEvent有两个子类ApplicationContextEvent、RequestHandledEvent
// 容器事件类public abstract class ApplicationContextEvent extends ApplicationEvent {}// 与web应用相关的事件RequestHandledEvent,当一个Http请求被处理后,产生该事件public class RequestHandledEvent extends ApplicationEvent {}
ApplicationContextEvent有4个子类ContextClosedEvent、ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent,分别表示容器启动、刷新、停止及关闭的事件。
RequestHandledEvent只有定义了DispatcherServlet时才会产生该事件,它的子类ServletRequestHandledEvent代表Servlet请求事件。
spring事件监听器
// 继承了JDK的EventListener接口// E extends ApplicationEvent是一个泛型public interface ApplicationListenerextends EventListener { // 只定义了一个方法 void onApplicationEvent(E event);}
ApplicationListener有两个子类GenericApplicationListener、SmartApplicationListener
public interface SmartApplicationListener extends ApplicationListener, Ordered { /** * 指定监听器支持哪种类型的容器事件 */ boolean supportsEventType(Class eventType); /** * 指定监听器仅对何种事件源对象做出响应 */ boolean supportsSourceType(Class sourceType);}public interface GenericApplicationListener extends ApplicationListener , 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
org.springframework spring-core 4.3.16.RELEASE org.springframework spring-context 4.3.16.RELEASE org.springframework spring-beans 4.3.16.RELEASE
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{ // 接收到事件后的处理逻辑 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); }}
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."); }}