文章目录

  • 基于继承的Event
  • 基于注解的Event
  • 异步侦听器

Spring提供了很方便的事件的处理机制,包括事件类ApplicationEvent和事件监听类ApplicationListener。 他实现的是设计者模式,如果实现了ApplicationListener接口的bean部署到Spring容器中,则每次ApplicationEvent发布到ApplicationContext时,都会通知该bean。

从Spring4.2开始,提供了基于注解的事件,即事件对象不一定要从ApplicationEvent来扩展。Spring会自动将其封装成一个事件对象。

下面是Spring的标准事件描述:

Event 解释
ContextRefreshedEvent 在初始化或刷新ApplicationContext时发布(例如,通过在ConfigurableApplicationContext接口上使用refresh()方法)。这里,“初始化”意味着加载所有bean,检测并激活后处理器bean,预先实例化单例,并且ApplicationContext对象准备好使用。只要上下文未关闭,只要所选的ApplicationContext实际上支持此类“热”刷新,就可以多次触发刷新。例如,XMLWebApplicationContext支持热刷新,但GenericApplicationContext不支持。
ContextStartedEvent 在可配置的ApplicationContext接口上使用start()方法启动ApplicationContext时发布。这里,“启动”意味着所有生命周期bean都会收到一个显式的启动信号。通常,此信号用于在显式停止后重新启动bean,但也可以用于启动尚未配置为自动启动的组件(例如,初始化时尚未启动的组件)。
ContextStoppedEvent 在可配置的ApplicationContext接口上使用stop()方法停止ApplicationContext时发布。这里,“停止”意味着所有生命周期bean都会收到一个明确的停止信号。停止的上下文可以通过start()调用重新启动。
ContextClosedEvent 在可配置的ApplicationContext接口上使用close()方法关闭ApplicationContext时发布。这里,“关闭”意味着所有的单例beans都被销毁了。封闭的环境达到了生命的尽头。无法刷新或重新启动。
RequestHandledEvent 一个特定于Web的事件,告诉所有bean HTTP请求已被服务。此事件在请求完成后发布。此事件仅适用于使用Spring的DispatcherServlet的Web应用程序。

基于继承的Event

你也可以自定义事件,下面是一个继承ApplicationEvent的例子:

public class BlackListEvent extends ApplicationEvent {private final String address;private final String content;public BlackListEvent(Object source, String address, String content) {super(source);this.address = address;this.content = content;}
}

若要发布自定义ApplicationEvent,在ApplicationEventPublisher上调用PublishEvent()方法。通常可以通过实现ApplicationEventPublisherAware接口来实现,如下所示:

public class EmailService implements ApplicationEventPublisherAware {private List<String> blackList;private ApplicationEventPublisher publisher;public void setBlackList(List<String> blackList) {this.blackList = blackList;}public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {this.publisher = publisher;}public void sendEmail(String address, String content) {if (blackList.contains(address)) {publisher.publishEvent(new BlackListEvent(this, address, content));return;}}
}

在配置时,Spring容器检测到EmailService实现了ApplicationEventPublisherAware,并自动调用setApplicationEventPublisher()。实际上,传入的参数是Spring容器本身。您正在通过其applicationEventPublisher接口与应用程序上下文进行交互。

要接收定制的applicationEvent,可以创建一个实现applicationListener的类,并将其注册为SpringBean。下面的示例显示了这样的类:

public class BlackListNotifier implements ApplicationListener<BlackListEvent> {private String notificationAddress;public void setNotificationAddress(String notificationAddress) {this.notificationAddress = notificationAddress;}public void onApplicationEvent(BlackListEvent event) {// notify appropriate parties via notificationAddress...}
}

这里使用了ApplicationListener 的BlackListEvent泛型。意味着onApplicationEvent()方法可以保持类型安全,避免任何向下强制转换的需要。

但请注意,默认情况下,事件侦听器同步接收事件。这意味着publishEvent()方法将一直阻塞,直到所有侦听器完成对事件的处理。

下面是注册和配置bean的例子:

<bean id="emailService" class="example.EmailService"><property name="blackList"><list><value>known.spammer@example.org</value><value>known.hacker@example.org</value><value>john.doe@example.org</value></list></property>
</bean><bean id="blackListNotifier" class="example.BlackListNotifier"><property name="notificationAddress" value="blacklist@example.org"/>
</bean>

Spring的事件机制是为同一应用程序上下文中SpringBean之间的简单通信而设计的。对于更复杂的企业集成需求,可以使用Spring Integration的AMQP模型来处理。

基于注解的Event

从Spring4.2开始,您可以使用EventListener注解在托管bean的任何公共方法上注册事件侦听器。BlackListNotifier程序可以改写如下:

public class BlackListNotifierAnnotation {private String notificationAddress;public void setNotificationAddress(String notificationAddress) {this.notificationAddress = notificationAddress;}@EventListenerpublic void processBlackListEvent(BlackListEvent event) {// notify appropriate parties via notificationAddress...}
}

如果您的方法应该监听多个事件,或者您想要定义它而不使用任何参数,那么也可以在注解本身上指定事件类型。以下示例显示了如何执行此操作:

    @EventListener({ContextStartedEvent.class, ContextRefreshedEvent.class})public void handleContextStart() {}

还可以使用定义spEL表达式的注解的条件属性添加其他运行时筛选,该表达式应与实际调用特定事件的方法相匹配。

下面的例子显示了如何重写通知程序,以便仅在事件的内容属性等于my-event时调用:

    @EventListener(condition = "#blEvent.content == 'my-event'")public void processBlackListSPELEvent(BlackListEvent blEvent) {// notify appropriate parties via notificationAddress...}

下表列出了上下文可用的项,以便您可以将它们用于条件事件处理:

name Location 描述 例子
Event root object 真实的ApplicationEvent #root.event
Arguments array root object 调用目标的参数 #root.args[0]
Argument name evaluation context 任何方法参数的名称。如果由于某种原因,名称不可用(例如,因为没有调试信息),参数名称也可以在 #a<#arg>下使用,其中#arg表示参数索引(从0开始)。 #blEvent or #a0 (也可以使用 #p0 or #p<#arg>)

异步侦听器

如果希望特定的侦听器异步处理事件,可以重用常规的@Async支持。下面是@Async的例子:

    @Async@EventListenerpublic void processBlackListEvent(BlackListEvent event) {// notify appropriate parties via notificationAddress...}

Listeners排序

如果需要先调用一个监听器,然后再调用另一个监听器,则可以将@order注解添加到方法声明中,如下所示:

    @EventListener@Order(12)public void processBlackListEvent(BlackListEvent event) {// notify appropriate parties via notificationAddress...}

本文的例子可以参考: event

更多精彩内容且看:

  • 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新
  • Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新
  • Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
  • java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程

更多教程请参考flydean的博客

Spring5参考指南:事件Event相关推荐

  1. Spring5参考指南:IOC容器

    文章目录 为什么使用Spring5 什么是IOC容器 配置元数据 实例化容器 XML嵌套 groovy bean定义DSL 使用容器 最近在翻译Spring Framework Documentati ...

  2. Spring5参考指南:AspectJ高级编程之Configurable

    文章目录 遇到的问题 @Configurable 原理 重要配置 遇到的问题 前面的文章我们讲到了在Spring中使用Aspect.但是Aspect的都是Spring管理的Bean. 现在有一个问题, ...

  3. Spring5参考指南:AOP代理

    文章目录 AOP代理 AOP Proxies原理 AOP代理 通常来说Spring AOP有两种代理方式,一种默认的JDK代理,只能代理接口,一种是CGLIB代理,可以代理具体的类对象. Spring ...

  4. Spring5参考指南: SpEL

    文章目录 Bean定义中的使用 求值 支持的功能 函数 Bean引用 If-Then-Else Elvis Safe Navigation 运算符 集合选择 集合投影 表达式模板化 SpEL的全称叫做 ...

  5. Spring5参考指南: BeanWrapper和PropertyEditor

    文章目录 BeanWrapper PropertyEditor BeanWrapper 通常来说一个Bean包含一个默认的无参构造函数,和属性的get,set方法. org.springframewo ...

  6. Spring5参考指南: Resources

    文章目录 内置Resource实现 ResourceLoader ResourceLoaderAware 资源作为依赖 构造ClassPathXmlApplicationContext-快捷方式 资源 ...

  7. Spring5参考指南:Environment

    文章目录 Profiles PropertySource 使用@PropertySource Spring的Environment接口有两个关键的作用:1. Profile, 2.properties ...

  8. Spring5参考指南:JSR 330标准注解

    文章目录 @Inject 和 @Named @Named 和 @ManagedBean 之前的文章我们有讲过,从Spring3.0之后,除了Spring自带的注解,我们也可以使用JSR330的标准注解 ...

  9. Spring5参考指南:组件扫描

    文章目录 组件扫描 @Component 元注解和组合注解 组件内部定义Bean元数据 为自动检测组件命名 为自动检测的组件提供作用域 生成候选组件的索引 组件扫描 上一篇文章我们讲到了annotat ...

最新文章

  1. PNAS-2018-玉米根际的大规模田间重复研究确定可遗传的微生物
  2. vlc android 编译 mac,在Mac中编译vlc-android小结
  3. mysql 报错ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executin
  4. matlab或_如何利用MATLAB计算圆周率
  5. 1001. 温度转换
  6. python为什么虚部是j不是i_Python基础02 基本数据类型
  7. python实现在线答题_python实现用户答题功能
  8. 数据挖掘原理与算法(第二版)
  9. Scrapy:爬取豆瓣图书
  10. AutoJS4.1.0实战教程---一键签到
  11. 中国科学院计算机研究生面试,19年中科院信工所考研经验分享【初试+复试】
  12. cmd中start 命令用法
  13. 关键词搜索-免费搜索关键词排名软件
  14. 【微信小程序】快进来弹钢琴啦~钢琴小程序源码分享
  15. 法定节假日加班没给三薪是不是犯法的
  16. 来自《星际迷航》的灵感启发
  17. 常见的浏览器指纹包含哪些
  18. fedora与redhat的区别
  19. iconv()函数转码
  20. springboot选择题、判断题

热门文章

  1. 高二计算机水平测试题,高二计算机学业水平测试 模拟试题(附答案)
  2. 八进制小数转化为十进制小数
  3. 利用找因子来找方程解的个数
  4. 5招减少网站恶意文件上传
  5. maven打包的各种方式和如何在使用maven-assembly-plugin打包时去掉assembly id
  6. 带你深入理解分布式事务,掌握后台分布式核心技术,PS:送5本!
  7. Kafka日志清理之Log Compaction
  8. 程序员应该知道的那些画图工具-第一期
  9. LeetCode:输出整体轮廓线和最长子数组长度
  10. mp4格式文件转码后处理(qt-faststart工具介绍)