SpringBoot重点详解--事件监听

ゝ一世哀愁。 2022-05-29 23:23 456阅读 0赞

目录

自定义事件监听

Springboot 启动事件监听


Springboot 事件监听为 Bean 与 Bean 之间的消息通信提供支持:当一个 Bean 做完一件事以后,通知另一个 Bean 知晓并做出相应处理,此时,需要后续 Bean 监听当前 Bean 所发生的事件。

自定义事件监听

在 Springboot 中实现自定义事件监听大致可以分为以下四个步骤:

  • 自定义事件,一般是继承 ApplicationEvent 抽象类;
  • 定义事件监听器,一般是实现 ApplicationListener 接口;
  • 注册监听器;
  • 发布事件。

    第一步:自定义事件,一般是继承 ApplicationEvent 抽象类。

    import org.springframework.context.ApplicationEvent;

    /**

    • 自定义事件,继承 ApplicationEvent
    • @author pjli
      */
      public class MyApplicationEvent extends ApplicationEvent {

      private static final long serialVersionUID = 1L;

      public MyApplicationEvent(Object source) {

      1. super(source);
      2. System.out.println("触发 MyApplicationEvent 事件...");

      }

    }

第二步:定义事件监听器,一般是实现 ApplicationListener 接口。

  1. import org.springframework.context.ApplicationListener;
  2. import org.springframework.stereotype.Component;
  3. /**
  4. * 事件监听器,实现 ApplicationListener 接口
  5. * @author pjli
  6. */
  7. @Component
  8. public class MyApplicationListener implements ApplicationListener<MyApplicationEvent>{
  9. @Override
  10. public void onApplicationEvent(MyApplicationEvent event) {
  11. System.out.println("监听到:"+event.getClass().getName()+"事件...");
  12. }
  13. }

第三步:注册监听器,有以下五种方式。

方式一:在启动类中,使用 ConfigurableApplicationContext.addApplicationListener() 方法注册。

  1. ConfigurableApplicationContext context = SpringApplication.run(MyApplication.class, args);
  2. // 注册 MyApplicationListener 事件监听器
  3. context.addApplicationListener(new MyApplicationListener());

方式二:使用 @Component 等注解将事件监听器纳入到 Spring 容器中管理。

  1. @Component
  2. public class MyApplicationListener implements ApplicationListener<MyApplicationEvent>{ //内容同上,此处省略 }

方式三:在 Springboot 核心配置文件 application.properties 中增加 context.listener.classes = [ 监听器全类名 ]。

  1. context.listener.classes=com.pengjunlee.listener.MyApplicationListener

该 context.listener.classes 配置项在 DelegatingApplicationListener 类的属性常量中指定。

方式四:使用 @EventListener 注解自动生成并注册事件监听器。

  1. import org.springframework.context.event.EventListener;
  2. import org.springframework.stereotype.Component;
  3. @Component
  4. public class MyEventHandler {
  5. @EventListener
  6. public void listenMyApplicationEvent(MyApplicationEvent event) {
  7. System.out.println("监听到:" + event.getClass().getName() + "事件...");
  8. }
  9. }

方式五:通过在 CLASSPATH/META-INF/spring.factories 中添加 org.springframework.context.ApplicationListener = [ 监听器全类名 ] 配置项进行注册.

  1. # Application Listeners
  2. org.springframework.context.ApplicationListener=com.pengjunlee.listener.MyApplicationListener

第四步:发布事件。

在程序启动类中可以使用 ApplicationContext.publishEvent() 发布事件,完整代码如下。

  1. import org.springframework.boot.SpringApplication;
  2. import org.springframework.boot.autoconfigure.SpringBootApplication;
  3. import org.springframework.context.ConfigurableApplicationContext;
  4. import com.pengjunlee.listener.MyApplicationEvent;
  5. import com.pengjunlee.listener.MyApplicationListener;
  6. @SpringBootApplication
  7. public class MyApplication {
  8. public static void main(String[] args) {
  9. ConfigurableApplicationContext context = SpringApplication.run(MyApplication.class, args);
  10. // 注册 MyApplicationListener 事件监听器
  11. context.addApplicationListener(new MyApplicationListener());
  12. // 发布 MyApplicationEvent 事件
  13. context.publishEvent(new MyApplicationEvent(new Object()));
  14. // context.getBean(MyEventHandler.class).publishMyApplicationEvent();
  15. context.close();
  16. }
  17. }

注意:可以通过以下代码将 ApplicationContext 注入到 Bean 中用来发布事件。

  1. @Autowired
  2. ApplicationContext applicationContext;

Springboot 启动事件监听

除了可以对自定义的事件进行监听,我们还能够监听 Springboot 的启动事件,Springbootg 共定义了以下5 种启动事件类型:

  • ApplicationStartingEvent:应用启动事件,在调用 SpringApplication.run() 方法之前,可以从中获取到 SpringApplication 对象,进行一些启动前设置。
  • ApplicationEnvironmentPreparedEvent:Environment准备完成事件,此时可以从中获取到 Environment 对象并对其中的配置项进行查看或者修改。
  • ApplicationPreparedEvent:ApplicationContext准备完成事件,接下来 Spring 就能够向容器中加载 Bean 了 。
  • ApplicationReadyEvent:应用准备完成事件,预示着应用可以接收和处理请求了。
  • ApplicationFailedEvent:应用启动失败事件,可以从中捕获到启动失败的异常信息进行相应处理,例如:添加虚拟机对应的钩子进行资源的回收与释放。

为了验证各个启动事件发生的前后,编写一个测试类进行测试,测试代码如下。

  1. import org.springframework.boot.Banner;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
  5. import org.springframework.boot.context.event.ApplicationFailedEvent;
  6. import org.springframework.boot.context.event.ApplicationPreparedEvent;
  7. import org.springframework.boot.context.event.ApplicationReadyEvent;
  8. import org.springframework.boot.context.event.ApplicationStartingEvent;
  9. import org.springframework.context.ApplicationListener;
  10. import org.springframework.context.ConfigurableApplicationContext;
  11. import org.springframework.core.env.ConfigurableEnvironment;
  12. /**
  13. * Springboot 启动事件测试
  14. * @author pjli
  15. */
  16. @SpringBootApplication
  17. public class MySpringBootApplication {
  18. public static void main(String[] args) {
  19. SpringApplication springApplication = new SpringApplication(MySpringBootApplication.class);
  20. // 添加 ApplicationStartingEvent 事件监听器
  21. springApplication.addListeners((ApplicationListener<ApplicationStartingEvent>) event -> {
  22. System.out.println("触发 ApplicationStartingEvent 事件...");
  23. SpringApplication application = event.getSpringApplication();
  24. application.setBannerMode(Banner.Mode.OFF);
  25. });
  26. // 添加 ApplicationEnvironmentPreparedEvent 事件监听器
  27. springApplication.addListeners((ApplicationListener<ApplicationEnvironmentPreparedEvent>) event -> {
  28. System.out.println("触发 ApplicationEnvironmentPreparedEvent 事件...");
  29. ConfigurableEnvironment environment = event.getEnvironment();
  30. System.out.println("event.name=" + environment.getProperty("event.name"));
  31. });
  32. // 添加 ApplicationPreparedEvent 事件监听器
  33. springApplication.addListeners((ApplicationListener<ApplicationPreparedEvent>) event -> {
  34. System.out.println("触发 ApplicationPreparedEvent 事件...");
  35. ConfigurableApplicationContext context = event.getApplicationContext();
  36. System.out.println("Application context name:" + context.getDisplayName());
  37. });
  38. // 添加 ApplicationReadyEvent 事件监听器
  39. springApplication.addListeners((ApplicationListener<ApplicationReadyEvent>) event -> {
  40. System.out.println("触发 ApplicationReadyEvent 事件...");
  41. });
  42. // 添加 ApplicationFailedEvent 事件监听器
  43. springApplication.addListeners((ApplicationListener<ApplicationFailedEvent>) event -> {
  44. System.out.println("触发 ApplicationFailedEvent 事件...");
  45. Throwable t = event.getException();
  46. System.out.println("启动失败:" + t.getMessage());
  47. });
  48. ConfigurableApplicationContext context = springApplication.run(args);
  49. context.close();
  50. }
  51. }

当应用正常启动时,打印内容如下:

  1. 触发 ApplicationStartingEvent 事件...
  2. 触发 ApplicationEnvironmentPreparedEvent 事件...
  3. event.name=pengjunlee
  4. 触发 ApplicationPreparedEvent 事件...
  5. Application context name:org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@49e202ad
  6. 触发 ApplicationReadyEvent 事件...

当应用重复启动两次,由于端口被占用而启动失败时,打印内容如下:

  1. 触发 ApplicationStartingEvent 事件...
  2. 触发 ApplicationEnvironmentPreparedEvent 事件...
  3. event.name=pengjunlee
  4. 触发 ApplicationPreparedEvent 事件...
  5. Application context name:org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@49e202ad
  6. 触发 ApplicationFailedEvent 事件...
  7. 启动失败:Connector configured to listen on port 8080 failed to start

由此可以看出 Springboot 启动事件的发生顺序是:Starting -->EnvironmentPrepared --> Prepared-->Ready/Failed

本文项目源码已上传至CSDN,资源地址:https://download.csdn.net/download/pengjunlee/10332845

发表评论

表情:
评论列表 (有 0 条评论,456人围观)

还没有评论,来说两句吧...

相关阅读

    相关 事件监听(基于SpringBoot示例)

    > 在实际开发中,业务代码与辅助代码的解耦是一个热点话题,如:通过AOP记录入参出参、使用事件监听记录错误信息等是一个不错的选择。 概述:         事件的发布与

    相关 springboot -03 事件监听

      在实际的开发中,常常遇到这种场景: 当某件事情完成后,需要通知其他的模块进行相应的处理。我们可以一个一个的发送请求去通知,但是更好的处理方式是通过事件监听来完成。事件监听