spring事件驱动模型--观察者模式在spring中的应用
spring中的事件驱动模型也叫作发布订阅模式,是观察者模式的一个典型的应用,关于观察者模式在之前的博文中总结过,http://www.cnblogs.com/fingerboy/p/5468994.html 这里主要讲一下Spring中的观察者模式的应用.
spring事件驱动模型的结构.

首先明确几个spring提供的类的概念
1.ApplicationEvent
public abstract class ApplicationEvent extends EventObject {
private static final long serialVersionUID = 7099057708183571937L;
private final long timestamp;
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
public final long getTimestamp() {
return this.timestamp;
}
}
ApplicationEvent继承自jdk的EventObject,所有的事件都需要继承ApplicationEvent,并且通过source得到事件源.该类的实现类ApplicationContextEvent表示ApplicaitonContext的容器事件.
2.ApplicationListener
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}
ApplicationListener继承自jdk的EventListener,所有的监听器都要实现这个接口,这个接口只有一个onApplicationEvent()方法,该方法接受一个ApplicationEvent或其子类对象作为参数,在方法体中,可以通过不同对Event类的判断来进行相应的处理.当事件触发时所有的监听器都会收到消息,如果你需要对监听器的接收顺序有要求,可是实现该接口的一个实现SmartApplicationListener,通过这个接口可以指定监听器接收事件的顺序.
3.ApplicationContext
事件机制的实现需要三个部分,事件源,事件,事件监听器,在上面介绍的ApplicationEvent就相当于事件,ApplicationListener相当于事件监听器,这里的事件源说的就是applicaitonContext.
ApplicationContext是spring中的全局容器,翻译过来是"应用上下文"的意思,它用来负责读取bean的配置文档,管理bean的加载,维护bean之间的依赖关系,可以说是负责bean的整个生命周期,再通俗一点就是我们平时所说的IOC容器.
Application作为一个事件源,需要显示的调用publishEvent方法,传入一个ApplicationEvent的实现类对象作为参数,每当ApplicationContext发布ApplicationEvent时,所有的ApplicationListener就会被自动的触发.
ApplicationContext接口实现了ApplicationEventPublisher接口,后者有一个很重要的方法:
public interface ApplicationEventPublisher {
void publishEvent(ApplicationEvent event);
}
我们常用的ApplicationContext都继承了AbstractApplicationContext,像我们平时常见的ClassPathXmlApplicationContext、XmlWebApplicationContex也都是继承了它,AbstractApplicationcontext是ApplicationContext接口的抽象实现类,在该类中实现了publishEvent方法
public void publishEvent(ApplicationEvent event) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
}
getApplicationEventMulticaster().multicastEvent(event);
if (this.parent != null) {
this.parent.publishEvent(event);
}
}
在这个方法中,我们看到了一个getApplicationEventMulticaster().这就要牵扯到另一个类ApplicationEventMulticaster.
4.ApplicationEventMulticaster
属于事件广播器,它的作用是把Applicationcontext发布的Event广播给所有的监听器.
在AbstractApplicationcontext中有一个applicationEventMulticaster的成员变量,提供了监听器Listener的注册方法.
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean { private ApplicationEventMulticaster applicationEventMulticaster;
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String lisName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(lisName);
}
}
}
在Spring 中使用事件监听机制的Demo
1. 建立事件类,继承applicationEvent
public class MyEvent extends ApplicationEvent {
public MyEvent(Object source) {
super(source);
System.out.println("my Event");
}
public void print(){
System.out.println("hello spring event[MyEvent]");
}
}
2.建立监听类,实现ApplicationListener接口
public class MyListener implements ApplicationListener{
public void onApplicationEvent(ApplicationEvent event) {
if(event instanceof MyEvent){
System.out.println("into My Listener");
MyEvent myEvent=(MyEvent)event;
myEvent.print();
}
}
}
这里再建一个监听类
public class MyListener implements ApplicationListener{
public void onApplicationEvent(ApplicationEvent event) {
if(event instanceof MyEvent){
System.out.println("into My Listener");
MyEvent myEvent=(MyEvent)event;
myEvent.print();
}
}
}
3.创建一个发布事件的类,该类实现ApplicationContextAware接口,得到ApplicationContext对象,使用该对象的publishEvent方法发布事件.
public class MyPubisher implements ApplicationContextAware {
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
}
public void publishEvent(ApplicationEvent event){
System.out.println("into My Publisher's method");
applicationContext.publishEvent(event);
}
}
3.在spring配置文件中,注册事件类和监听类,当然使用注解的方式也是一样的.(略)
4.测试
public class MyTest {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("classpath:spring/application-database.xml");
MyPubisher myPubisher=(MyPubisher) context.getBean("myPublisher");
myPubisher.publishEvent(new MyEvent("1"));
}
}
查看控制台打印
my Event
into My Publisher's method
into My Listener
hello spring event[MyEvent]
into My second Listener
hello spring event[MyEvent]
总结
spring的事件驱动模型使用的是 观察者模式
通过ApplicationEvent抽象类和ApplicationListener接口,可以实现ApplicationContext事件处理
监听器在处理Event时,通常会进行判断传入的Event是不是自己所想要处理的,使用instanceof关键字
ApplicationEventMulticaster事件广播器实现了监听器的注册,一般不需要我们实现,只需要显示的调用applicationcontext.publisherEvent方法即可
spring事件驱动模型--观察者模式在spring中的应用的更多相关文章
- 带你自定义实现Spring事件驱动模型
Spring 事件驱动模型概念 Spring 事件驱动模型就是观察者模式很经典的一个应用,我们可以通过Spring 事件驱动模型来完成代码的解耦. 三角色 Spring 事件驱动模型或者说观察者模式需 ...
- 详解Spring事件驱动模型
转载自:http://jinnianshilongnian.iteye.com/blog/1902886#comments 事件驱动模型简介 事件驱动模型也就是我们常说的观察者,或者发布-订阅模型:理 ...
- spring 事件驱动模型简介
事件驱动模型简介 事件驱动模型也就是我们常说的观察者,或者发布-订阅模型:理解它的几个关键点: 首先是一种对象间的一对多的关系:最简单的如交通信号灯,信号灯是目标(一方),行人注视着信号灯(多方): ...
- 事件驱动模型和异步IO多路复用
事件驱动模型 协程:遇到IO操作就切换. 但什么时候切回去呢?怎么确定IO操作完了? 很多程序员可能会考虑使用“线程池”或“连接池”.“线程池”旨在减少创建和销毁线程的频率,其维持一定合理数量的线程, ...
- IO事件驱动模型
1:IO事件驱动模型简介 通常,我们写服务器处理模型的程序时,有以下几种模型: (1)每收到一个请求,创建一个新的进程,来处理该请求: (2)每收到一个请求,创建一个新的线程,来处理该请求: (3)每 ...
- python网络编程--事件驱动模型
论事件驱动与异步IO 事件驱动模型:根据事件的触发去干什么事,就是根据一个事件做反应 原文:http://www.cnblogs.com/alex3714/articles/5248247.html常 ...
- [案例一] Spring中的事件驱动模型(机制)
事件驱动模型是观察者模式的另一种形态,观察者相当于监听器,被观察者相当于事件源 事件源产生事件,监听器监听事件 以用户注册时候,要发送邮件和发送短信举例说明 定义一个事件 /** * spring会自 ...
- 从spring框架中的事件驱动模型出发,优化实际应用开发代码
一.事件起源 相信很多人在使用spring框架进行开发时,都会遇到这样的需求:在spring启动后,立即加载部分资源(例如:spring启动后立刻加载资源初始化到redis中).当我去解决这个问题时发 ...
- 三种方式实现观察者模式 及 Spring中的事件编程模型
观察者模式可以说是众多设计模式中,最容易理解的设计模式之一了,观察者模式在Spring中也随处可见,面试的时候,面试官可能会问,嘿,你既然读过Spring源码,那你说说Spring中运用的设计模式吧, ...
随机推荐
- (简单) POJ 2029 Get Many Persimmon Trees,暴力。
Description Seiji Hayashi had been a professor of the Nisshinkan Samurai School in the domain of Aiz ...
- (中等) HDU 3416 Marriage Match IV,SPFA+SAP。
Description Do not sincere non-interference. Like that show, now starvae also take part in a show, b ...
- 增量式PID的stm32实现(转)
源:增量式PID的stm32实现,整定过程 首先说说增量式PID的公式,这个关系到MCU算法公式的书写,实际上两个公式的写法是同一个公式变换来得,不同的是系数的差异. 资料上比较多的是: 还有一种是: ...
- iOS调用相机,相册,上传头像
一.新建工程 二.拖控件,创建映射 三.在.h中加入delegate @interface ViewController : UIViewController 复制代码 四.实现按钮事件 -(IBAc ...
- Core Data需求
大家都在讨论怎么使用Core Data,但是什么时候用到Core Data,这好像是大家很少讨论的问题 我们使用Core Data ,主要用来存储两种类型的数据:固定的数据,和 可能变化的数据. 1. ...
- cocharan-Armitage trend test
Cochran-Armitage trend test是我们常说的趋势卡方检验,一般是针对基因型的2*3列联表的.譬如说三种基因型,如果按照某一个allele来看,可以有0.1.2个拷贝,是有序的,我 ...
- C++第一天学习
代码1 #include<iostream> int main(){ int a; std::cout << "hello c++" << st ...
- js原生之scrollTop、offsetHeight和offsetTop等属性用法详解
scrollTop.offsetHeight和offsetTop等属性用法详解:标题中的几个相关相关属性在网页中有这大量的应用,尤其是在运动框架中,但是由于有些属性相互之间的概念比较混杂或者浏览器兼容 ...
- 使用ProgressDialog创建进度对话框
ProgressDialog代表了进度对话框,程序只要创建ProgressDialog实例,并将它显示出来就是一个进度对画框.使用ProgressDialog创建进度对话框有如下两种方式. ①如果只是 ...
- Unity游戏开发——自动为动画剪辑添加事件 之 最后几帧的事件不能被调用的问题
最近在做一个根据配置表自动生成动画剪辑clip以及controller的功能.做法是根据配置表配置的动作以及每个动作的关键帧,自动为每个clip添加事件.这样做可以把动画的事件处理在游戏运行之前就计算 ...