Spring的事件与异步事件

观察者模式

Spring事件体系是观察者模式的典型应用。观察者模式简单来说即所有观察者继承一个包含触发方法的父类并重写该方法,然后注册到被观察者的一个列表中。当被观察者发生变化时通过调用列表中所有已注册观察者的触发方法,使观察者得到通知,从而作进一步处理。关于观察者模式的具体描述网上有很多,这里不再赘述。

Spring事件体系

Spring事件体系包含三个部件:

  • 事件:ApplicationEvent
  • 事件监听器:ApplicationListener,对监听到的事件进行处理。
  • 事件广播器:ApplicationEventMulticaster,将publish的事件广播给所有的监听器。通常情况下无需自行实现,spring默认提供了SimpleApplicationEventMulticaster。

Spring事件实例

这里我们模拟一个交通信号灯状态改变的事件,而相应的监听者应当根据交通信号灯的状态做出不同的反应:红灯停,黄灯等,绿灯行。
首先定义一个LightEvent继承ApplicationEvent来描述交通信号灯状态改变的事件。其中lightColor描述信号灯状态,1:红灯 2:黄灯 3:绿灯。

事件监听器实现ApplicationListener接口的onApplicationEvent方法,<LightEvent>则表明该监听器只关心LightEvent事件,不关心其他类型的事件。

需要注意的是,事件监听器需要作为Bean注册到spring才能实现对事件的监听,这里用@Component注解配合spring配置文件的component-scan使用。当然也可以使用普通的基于xml的Bean配置方式。

最后是测试函数,调用了ApplicationContext的publishEvent方法。

输出结果为:

这里注意两个输出的顺序,即使我们在监听器中调用了sleep方法,对于事件的处理“红灯停”还是先于“things after publish”输出,说明事件的触发默认是以同步方式进行的。

Spring事件原理

Spring事件体系基于ApplicationContext实现,其构建过程主要包含在ApplicationContext接口的抽象实现类AbstractApplicationContext中。AbstractApplicationContext中持有了applicationEventMulticaster成员变量,其初始化(initApplicationEventMulticaster)以及事件监听器的注册(registerListeners)过程可以在refresh函数中看到。

  • 初始化事件广播器

在初始化事件广播器的过程中,Spring会首先检查是否存在用户自定义的名称为“applicationEventMulticaster”且实现了ApplicationEventMulticaster接口的Bean。若存在则使用用户自定义的ApplicationEventMulticaster作为事件广播器,否则使用默认的SimpleApplicationEventMulticaster。

  • 注册事件监听器

最主要的步骤为通过反射获取所有实现了ApplicationListener接口的Bean,并调用addApplicationListenerBean方法将其注册到applicationEventMulticaster中。addApplicationListenerBean方法的实现在AbstractApplicationEventMulticaster中:

其中ListenerRetriever的数据结构如下,可以看到applicationListenerBeans为String的集合。注册事件监听器的根本就是把事件监听器的名字加入该集合中。

  • 发布事件

publishEvent(Object event)最终调用了publishEvent(Object event, ResolvableType eventType),其中最关键的部分即调用了applicationEventMulticaster的multicastEvent方法,我们可以看一下SimpleApplicationEventMulticaster中multicastEvent方法的实现:

该方法获取所有注册了给定事件的监听器,默认情况下executor为null,因此会直接调用invokeListener方法,在该方法中调用了listener的onApplicationEvent方法,实现对事件监听器的通知,完成事件发布。这样默认的调用方式是同步的,主流程需要等待所有listener的onApplictionEvent方法执行完毕才能继续执行。

Spring异步事件

通常情况下,主流程并不关心各个listener对事件的处理情况,也无需等待事件处理结果,此时需要通过异步的方式调用事件监听器的onApplicationEvent方法。实现异步的方式主要有两种:

  • 设置SimpleApplicationEventMulticaster的executor

    定义一个Bean,id为applicationEventMulticaster(该id必须与APPLICATION_EVENT_MULTICASTER_BEAN_NAME一致
    ),类型为SimpleApplicationEventMulticaster,使用task:executor定义一个线程池,并将其指定给SimpleApplicationEventMulticaster的taskExecutor成员,则在执行multicastEvent时会通过该线程池调用监听器的onApplicationEvent方法,从而实现异步调用。
  • 自定义ApplicationEventMulticaster继承AbstractApplicationEventMulticaster

    此时同样需要在spring的配置文件中配置这个bean:

基于注解的事件与异步事件

Spring4.2开始提供了@EventListener注解,使得监听器不再需要实现ApplicationListener接口,只需要在监听方法上加上该注解即可,方法不一定叫onApplicationEvent,但有且只能有一个参数,指定监听的事件类型。如:

对于异步事件,Spring3.0开始提供了@Async注解,可以方便快速地实现异步事件。

相应配置加入(不再需要指定id为applicationEventMulticaster的Bean):

参考资料:

1. 《Spring事件体系》http://blog.csdn.net/caihaijiang/article/details/7460888

2. 《spring 异步配置要点》 http://www.cnblogs.com/clarkapp/archive/2012/10/16/2726963.html

代码下载地址http://pan.baidu.com/s/1slQUJzJ

Spring的事件与异步事件》上有1条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注