Spring的ApplicationContext能够发布事件并且允许注册相应的事件监听器,因此它拥有一套完善的事件发布和监听机制。我们知道Java通过java.util.EventObject类和java.util.EventListener接口描述 事件和监听器,某个组件或框架要建立自己的事件发布和监听机制,一班都要通过扩展它们进行定义。在事件体系中,除了事件和监听器以外,要有三个重要的概念。
事件源:事件的生产者,任何一个EventObject都必须拥有一个事件源;
事件监听注册表:组件或者框架的事件监听器不可能漂浮在水里和悬在空中,而必须有所依存。也就是说组件或者框架必须提供一个地方保存事件监听器,这既是事件监听器注册表。一个事件监听器注册到组件或者框架中,其实就是保存在佳宁器注册表里面,当组件和框架中的事件源产生事件时就会将事件通知这些位于注册表中的监听器;
事件广播器:它是事件与事件监听器的沟通桥梁,负责把事件通知给事件监听器。
事件源,事件监听器注册表和事件广播器这三个角色有时候可以由一个对象承担,如java.swing包中的Jbutton,Jcheck等组件,他们分别集以上三角色于一身。
在分析事件体系后,我们会发现事件体系其实就是观察者模式的一种具体实现方式,它并没有任何神秘的地方。之所以以组件或框架的事件会让一些开发者觉得神奇,就是因为组建或者框架通过观察者模式很好地封装了事件模型并透明地供给提供者使用,使用这只需要按其设定方式定义并注册事件监听器,事件体系就可以正常地工作,因此我们很少回去关注它的内部实现机理。
写一个模拟邮件发送器MailSender
(1)先构造出一个发送邮件的事件,该事件继承了Spring的ApplicationEvent
package com.hegx.spring.springevent; import org.springframework.context.ApplicationEvent; /** * @Author: hegx * @Description:模拟邮件发送器MailSender,它向目的地发送邮件时,将产生一个MailSendEvent的事件,容器中注册了该监听器MailSendEvenListener * @Date: 14:09 2017/7/14 */ public class MailSendEvent extends ApplicationEvent{ //邮件发送的目的 private String to; //扩展超类的构造器,增添了目的属性 public MailSendEvent(Object source,String to) { super(source); this.to = to; } //get的方法 public String getGetTo() { return this.to; } }
(2)构建该事件的监听器,负责监控MailSenderEvent
package com.hegx.spring.springevent; import org.springframework.context.ApplicationListener; /** * @Author: hegx * @Description:事件监听器MailSendEvenListener负责监听MailSendEvent事件 * @Date: 14:15 2017/7/14 */ public class MailSendEvenListener implements ApplicationListener<MailSendEvent> { /** * 该方法接受Application事件对象,负责处理MailSendEven事件 * */ @Override public void onApplicationEvent(MailSendEvent mailSendEvent) { System.out.println("MailSendListener:向"+mailSendEvent.getGetTo()+"发送完一封邮件"); } }
(3)构建发送事件的主体MailSender,改类必须实现ApplicationContextAware接口
package com.hegx.spring.springevent; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @Author: hegx * @Description:MailSender要拥有发布事件的能力,必须实现ApplicationContextAware的接口 * @Date: 14:31 2017/7/14 */ public class MailSender implements ApplicationContextAware { private ApplicationContext applicationContext; /** * ApplicationContextAware的接口方法,以便容器在启动时注入容器实例 * **/ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } public void sendMail(String to) { System.out.println("MailSender:模拟发送邮件"); //通过构造器产生一个MailSendEvent的事件 MailSendEvent mailSendEvent = new MailSendEvent(applicationContext,to); //向容器中的所有事件监听器发送事件 applicationContext.publishEvent(mailSendEvent); } public static void main(String[] args) { ClassPathXmlApplicationContext cxac = new ClassPathXmlApplicationContext("classpath:spring.xml"); MailSender mailSender = (MailSender) cxac.getBean("mailSender"); mailSender.sendMail("751762100@qq.com"); } }
(4)运行main方法后的结果:
MailSender:模拟发送邮件
MailSendListener:向751762100@qq.com发送完一封邮件
MailSendListener:向751762100@qq.com发送完一封邮件