当前位置:   article > 正文

ApplicationEvent与ApplicationListener_applicationlistener

applicationlistener

前言:

    Spring的世界中有这么一对好基友,两个人总是同时出现,相爱相杀。这就是ApplicationEvent与ApplicationListener。感觉有点像小偷和警察,只要ApplicationEvent一出现,ApplicationListener就会发现TA。

    下面我们就来看一个示例,是Spring官方文档提供的示例。

    笔者大概说明一下这个示例的背景:就是一个发送邮件的功能,如果在发送邮件的过程中,发现邮件地址在黑名单内,那么就发送一个黑名单事件,负责监听该事件的Listener就会监听到,打印相关信息;如果不在黑名单内,就直接发送出去。

 

    下面就先看下官网提供的示例吧

 

1.发送邮件的黑名单事件与监听

    1)创建事件BlackListEvent

  1. public class BlackListEvent extends ApplicationEvent {
  2. private final String address;
  3. private final String content;
  4. public BlackListEvent(Object source, String address, String content) {
  5. super(source);
  6. this.address = address;
  7. this.content = content;
  8. }
  9. public String getAddress() {
  10. return address;
  11. }
  12. public String getContent() {
  13. return content;
  14. }
  15. // accessor and other methods...
  16. }

    2)创建发送事件器

  1. public class EmailService implements ApplicationEventPublisherAware {
  2. private List<String> blackList;
  3. private ApplicationEventPublisher publisher;
  4. public void setBlackList(List<String> blackList) {
  5. this.blackList = blackList;
  6. }
  7. @Override
  8. public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
  9. this.publisher = publisher;
  10. }
  11. // 主要逻辑就在这里,发送邮件之前先做一次判断,判断是否在黑名单内
  12. public void sendEmail(String address, String content) {
  13. if (blackList.contains(address)) {
  14. publisher.publishEvent(new BlackListEvent(this, address, content));
  15. return;
  16. }
  17. // send email...
  18. System.out.println(address + "邮件已被发送...");
  19. }
  20. }

    3)创建事件监听器

  1. package eventListener;
  2. import org.springframework.context.ApplicationListener;
  3. import org.springframework.stereotype.Component;
  4. public class BlackListNotifier implements ApplicationListener<BlackListEvent> {
  5. @Override
  6. public void onApplicationEvent(BlackListEvent event) {
  7. System.out.println(event.getAddress() + "已被列入黑名单,不能发送邮件");
  8. }
  9. }

    经过上面三步,事件、事件发送器、事件监听器都创建完毕。下面开始测试

    4)创建Configuration,封装具体的Bean

  1. @Configuration
  2. public class ListenerConfig {
  3. @Bean
  4. public EmailService emailService(){
  5. EmailService emailService = new EmailService();
  6. // 在这里添加黑名单集合
  7. emailService.setBlackList(Arrays.asList("known.spammer@example.org","known.hacker@example.org","john.doe@example.org","blackAddredd@123.com"));
  8. return emailService;
  9. }
  10. @Bean
  11. public BlackListNotifier blackListNotifier(){
  12. return new BlackListNotifier();
  13. }
  14. }

    5)测试类

  1. public class ListenerTest {
  2. @Test
  3. public void listener() {
  4. AnnotationConfigApplicationContext applicationContext
  5. = new AnnotationConfigApplicationContext(ListenerConfig.class);
  6. EmailService emailService = applicationContext.getBean(EmailService.class);
  7. emailService.sendEmail("blackAddredd@123.com", "content");// 在黑名单内部
  8. emailService.sendEmail("normalAddr@123.com", "content");// 不在黑名单内部
  9. }
  10. }
  11. // res
  12. blackAddredd@123.com已被列入黑名单,不能发送邮件
  13. normalAddr@123.com邮件已被发送...

    总结:从结果可以看出,在黑名单内部的邮箱触发了Event,并且被Listener监听到,而正常的邮箱地址则不会。

    以上就是Event与Listener的一个简单示例(来自官网)。

    那下面我们从示例倒推,我们能用Event和Listener做什么呢?哪些场景比较适合用这个组合呢?

 

2.Event和Listener简析

    仔细看下,会有一种熟悉的感觉,这不就是我们的观察者模式嘛

    对的,就是观察者模式,设计的初衷就是为了业务系统之间的解耦,提高可扩展性和可维护性。

    就像我们在使用MQ发送消息接收消息的时候,发送者并不关心谁来接收消息,只关心消息是否能发送出去,而接收者也并不关心消息从哪里被发送过来,只需要在接收到消息之后进行处理即可。

    所以,我们完全可以当MQ的心态来使用,如果我们希望两个事件完全解耦,两者之间不要有任何直接的联系,那么就可以考虑使用Event和Listener

 

3.Listener的其他用法

    Spring官网为我们展示了更多的监听器用法。笔者就在这里简单列一下

    1)Annotation用法

  1. public class BlackListNotifierAnnotation {
  2. @EventListener
  3. public void processBlackListEvent(BlackListEvent event) {
  4. System.out.println(event.getAddress() + "已被列入黑名单,不能发送邮件");
  5. }
  6. }

    Spring的强大之处就在于,基本所有的配置都可以用Annotation来代替

    我们在开发之中,也可以多用Annotation,代码更简洁

 

    2)异步监听处理

  1. public class BlackListNotifierAnnotation {
  2. @EventListener
  3. @Async
  4. public void processBlackListEvent(BlackListEvent event) {
  5. System.out.println(event.getAddress() + "已被列入黑名单,不能发送邮件");
  6. }
  7. }

    如果我们希望监听器的处理是异步的,那么可以考虑使用@Async来处理

 

    3)多Listener

  1. public class BlackListNotifierAnnotation1 {
  2. @EventListener
  3. @Order(1)
  4. public void processBlackListEvent(BlackListEvent event) {
  5. // 处理事件1...
  6. doSomething1();
  7. }
  8. }
  9. public class BlackListNotifierAnnotation2 {
  10. @EventListener
  11. @Order(2)
  12. public void processBlackListEvent(BlackListEvent event) {
  13. // 处理事件2...
  14. doSomething2();
  15. }
  16. }

    这里需要注意下,我们的监听器不是说只能有一个,可以有多个,假如一个事件,在被触发后,处理流程比较长,设计到多个系统,那么可以考虑使用多监听器,每个监听器处理一部分事情。

    如果在意监听器的处理顺序,可以使用@Order来标记处理顺序

 

4.Spring提供的事件列表

    来自于https://www.jianshu.com/p/ef2cee8c5dd1  

 

序号Spring 内置事件 & 描述
1ContextRefreshedEvent ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext 接口中使用 refresh() 方法来发生。
2ContextStartedEvent当使用 ConfigurableApplicationContext 接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。
3ContextStoppedEvent当使用 ConfigurableApplicationContext 接口中的 stop() 方法停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作。
4ContextClosedEvent当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。
5RequestHandledEvent这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。


 

参考:

https://docs.spring.io/spring/docs/4.3.23.RELEASE/spring-framework-reference/htmlsingle/ 

代码地址:https://github.com/kldwz/springstudy  

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/157184?site
推荐阅读
相关标签
  

闽ICP备14008679号