Spring 事件发布
Author: xiaolu
概要:
Spring的ApplicationContext在BeanFactory的基础上,支持事件的发布(包括同步-默认,和异步事件)。
事件发布和事件监听处理本质上是观察者模式的一种使用方式。对于Spring事件的发布,包含三个部分: 事件实体、事件监听器、事件发布者。
事件实体:
事件实体定义了什么事件,同时包含了要传递的参数信息。Spring的事件发布中,自定义事件实体需要继承ApplicationEvent类。即所有的事件都是ApplicationEvent类的子类。
事件监听者:
事件监听者,即对某个事件感兴趣的部分,在特定事件发生后,需要去进行某种逻辑的处理。Spring中事件监听者需要实现ApplicationListener接口。在其onApplicationEvent函数中进行事件的处理。
事件发布者:
事件发布者即发布事件的部分,它推动了事件流程的开始。Spring中,事件的发布可以使用ApplicationContext类的publishEvent方法来进行发布。
代码示例:
1) Java配置部分(替代xml文件配置方式)
2) 事件定义
此处定义一个StartEvent事件,继承于ApplicationEvent
3) 事件监听者
通过泛型参数给出具体要监听的事件类型
4) 事件发布
通过ApplicationContext的publishEvent来发布事件。
在这里出现了EventUtils类,其实是可以通过第11行的context来发布事件,但是在web程序中,我们是无法直接获得ApplicationContext对象的。(这里是演示,因此直接new获取了ApplicationContext)。要发布事件,就需要有ApplicationContext对象。那么如何获取ApplicationContext对象呢?在Spring中,如果实现XAware接口,那么Spring在构造bean时,会将对应的X注入到这个Bean中,因此只需要实现ApplicationContextAware即可。
在这里,EventUtils类实现了ApplicationContextAware接口,因此Spring容器在构造EventUtils这个bean时,检测到其实现了ApplicationContextAware接口,因为会将ApplicationContext实例注入进来,我们就可以使用它来发布事件了。
还有一种方式是实现ApplicationEventPublisherAware接口,Spring会注入ApplicationEventPublisher类型对象,通过它来发布实现。(其实注入进来的对象就是ApplicationContext对象,因为ApplicationContext接口继承自ApplicationEventPublisher接口。
网上经常给出实现是实现ApplicationContextAware/ApplicationEventPublisherAware接口,来发布事件,其原因是:为了持有ApplicationContext对象。
事件的同步和异步:
以上的事件发布则是使用的同步方式,如果要使用异步方式,所谓异步方式就是事件发布后不用等待事件监听者执行完成就返回。其实现是事件监听者使用了新的线程而非发布线程来执行事件处理逻辑。
@Async 和 @EnableAsync
在事件监听类的处理方法上设置@Async标签,同时在配置文件(配置类)上加上@EnableAsync即可。
代码示例:
事件监听者:
配置类(配置文件)
在spring中实现了AsyncConfigurer接口,并提供了Executor,否则会抛出异常(在SpringBoot中则不用实现此接口)。
还有一种实现异步的方式:
如果觉得监听器实现ApplicationListener<Event>接口具有侵入性,也可以通过注解方式而不用去实现接口:
效果是一样的:
如果去掉@Async和@EnableAsync,则结果是:
可以看到都是使用的main主线程来执行(也即是在同一个线程中执行了事件的发布者和监听者的事件处理逻辑,自然是同步的)。
来源:https://www.cnblogs.com/xiao-lu/p/9575537.html