【Spring Boot 三】SpringBoot中事件与通知

简介: 【Spring Boot 三】SpringBoot中事件与通知

前言

在SpringBoot启动过程中,有下面两行代码

  SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();

简单概括来说,他的作用是:


通过spring.factories文件中找到所有需要被实例化的SpringApplicationRunListener的实现类;并将其实例化,然后执行starting方法; 在SpringBoot中这个实现类只有EventPublishingRunListener; 这就涉及到了Spring中的事件与通知机制了


正文源码解析

事件发布监听器 EventPublishingRunListener

这个类是SpringBoot用来监听Spring运行过程事件,监听到对应的事件之后,它会把对应的事件广播出去;


这个类实现了SpringApplicationRunListener接口;具体的事件有以下

  /**在首次启动run方法时立即调用。可用于非常*早期的初始化。 */
  void starting();
  /**在环境准备好之后,但在创建* {@link ApplicationContext}之前调用。*/
  void environmentPrepared(ConfigurableEnvironment environment);
  /**在创建和准备{@link ApplicationContext}之后调用,但在加载源之前调用*。 * @param context应用程序上下文*/
  void contextPrepared(ConfigurableApplicationContext context);
  /**
   * Called once the application context has been loaded but before it has been
   * refreshed.
   * @param context the application context
   */
  void contextLoaded(ConfigurableApplicationContext context);
  /**
   * The context has been refreshed and the application has started but
   * {@link CommandLineRunner CommandLineRunners} and {@link ApplicationRunner
   * ApplicationRunners} have not been called.
   * @param context the application context.
   * @since 2.0.0
   */
  void started(ConfigurableApplicationContext context);
  /**
   * Called immediately before the run method finishes, when the application context has
   * been refreshed and all {@link CommandLineRunner CommandLineRunners} and
   * {@link ApplicationRunner ApplicationRunners} have been called.
   * @param context the application context.
   * @since 2.0.0
   */
  void running(ConfigurableApplicationContext context);
  /**
   * Called when a failure occurs when running the application.
   * @param context the application context or {@code null} if a failure occurred before
   * the context was created
   * @param exception the failure
   * @since 2.0.0
   */
  void failed(ConfigurableApplicationContext context, Throwable exception);

在来看看EventPublishingRunListener 的构造函数

image.png

特别说明一下: SpringApplicationRunListener的实现类的构造函数必须是 上面两个参数;如果没有对应的构造函数的话会报错;这是因为在实例化这个对象的时候特别指定的是这两个参数的构造函数,如果找不到就实例化不了;


我们可以看到这个类主要的一个属性是 SimpleApplicationEventMulticaster;


应用程序事件广播器 SimpleApplicationEventMulticaster

这是Spring中的一个类,事件广播器;他的职责就是把监听到的应用程序事件,广播给所有的监听者; 最终调用监听者ApplicationListener的onApplicationEvent方法;


既然要广播给所有的监听者,那得要知道有哪些监听者,上面

image.png

上面就是将监听者给保存到对象中; (注意: 这里保持的是spring.factories方式获取到的,但是获取的时候 还会读取被Spring管理的ApplicationListener的bean; 可是能不能读取到 Spring管理的bean要看事件触发的时机,比如 staring事件,这个时间Spring容器都还没有初始化,那些被注解管理的ApplicationListener就不会被读取到)

然后有事件发生时候最终会调用

  @Override
  public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
      Executor executor = getTaskExecutor();
      if (executor != null) {
        executor.execute(() -> invokeListener(listener, event));
      }
      else {
        invokeListener(listener, event);
      }
    }
  }

getApplicationListeners(event, type) 根据事件类型 找到对应事件的监听类;

image.png

listener.onApplicationEvent(event);


那么这些listeners从哪里来的呢 -> application.getListeners()


加载监听者 ApplicationListener

ApplicationListener是一个接口,只有一个方法onApplicationEvent(E even); 每个实现类要实现这个方法; 入参E是一个事件类ApplicationEvent; 将实现类配置到spring.factories之后就会被 SimpleApplicationEventMulticaster广播着管理;后续有事件发生就会通知到实现类;


加载时机

image.png

在启动之初,上述就已经把在 spring.factories 中找到的所有ApplicationListener给实例化了;

并将其设置到属性List<ApplicationListener<?>> listeners;中;


扩展

既然我们知道了Spring中的事件与通知机制,那么我们是否能做一些扩展了


SpringBoot开始启动的时候 打印一下日志

我们已经知道启动的方法在 SpringApplicationRunListener.starting() ;

  public void starting() {
    for (SpringApplicationRunListener listener : this.listeners) {
      listener.starting();
    }
  }

① 继承一个ApplicationListener接口

public class StartApplicationListenerInFactories implements ApplicationListener<ApplicationStartingEvent>, Ordered {
    @Override
    public void onApplicationEvent(ApplicationStartingEvent event) {
            System.out.println("应用程序开始启动-监听器-----在Factories中方式;args.name:");
           Arrays.asList(event.getArgs()).stream().forEach(x -> System.out.println(x));
    }
    @Override
    public int getOrder() {
        return 0;
    }
}

并在spring.factories文件中加入

image.png

启动看结果

image.png

可以注意到,我们启动时候传入的入参也是会一起放到SpringApplicationEvent中的;


如果不在spring.factories中配置,直接用注解被管理可以吗

不可以,在应用程序刚开始启动的时候,Spring容器都还没有初始化,是选择用spring.factories方式还是用注解管理的方式,需要看调用的时机; 像staring这个时机就不行;


那哪些时机可以? TODO… 单独文章分析


②. 实现一个SpringApplicationRunListener类

上面一种方式 是用SpringBoot内部的通知类EventPublishingRunListener 来通知到所有监听对应事件的监听者; 所以上面的方式只需要写一个监听者监听对应的事件就行了;

EventPublishingRunListener 是实现了类SpringApplicationRunListener的实现类;那么我们也可以直接实现一个 SpringApplicationRunListener类呀;

public class MyRunListener implements SpringApplicationRunListener, Ordered {
    //注意 SpringApplicationRunListener 的构造函数必须带有下面两个参数; 因为在实例化的时候查找的构造函数指定了这两个参数的
    public MyRunListener(SpringApplication application, String[] args) {
    }
    @Override
    public void starting() {
        System.out.println("MyRunListener.......staring");
    }
    //省略..
}

image.png

自定义事件通知与监听

SpringBoot自定义通知与监听


总结

SpringApplicationRunListener 定义了应用程序启动的过程每个节点事件; SpringBoot会将每个节点事件通知给监听者们Listeners ;开发者可以实现接口ApplicationListener 来实现自己的逻辑;



相关文章
|
9天前
|
Java 开发者 Spring
java springboot监听事件和处理事件
通过上述步骤,开发者可以在Spring Boot项目中轻松实现事件的发布和监听。事件机制不仅解耦了业务逻辑,还提高了系统的可维护性和扩展性。掌握这一技术,可以显著提升开发效率和代码质量。
75 33
|
7天前
|
缓存 安全 Java
Spring Boot 3 集成 Spring Security + JWT
本文详细介绍了如何使用Spring Boot 3和Spring Security集成JWT,实现前后端分离的安全认证概述了从入门到引入数据库,再到使用JWT的完整流程。列举了项目中用到的关键依赖,如MyBatis-Plus、Hutool等。简要提及了系统配置表、部门表、字典表等表结构。使用Hutool-jwt工具类进行JWT校验。配置忽略路径、禁用CSRF、添加JWT校验过滤器等。实现登录接口,返回token等信息。
134 12
|
11天前
|
Java 开发者 Spring
java springboot监听事件和处理事件
通过上述步骤,开发者可以在Spring Boot项目中轻松实现事件的发布和监听。事件机制不仅解耦了业务逻辑,还提高了系统的可维护性和扩展性。掌握这一技术,可以显著提升开发效率和代码质量。
43 13
|
15天前
|
Java Spring
Java Spring Boot监听事件和处理事件
通过上述步骤,我们可以在Java Spring Boot应用中实现事件的发布和监听。事件驱动模型可以帮助我们实现组件间的松耦合,提升系统的可维护性和可扩展性。无论是处理业务逻辑还是系统事件,Spring Boot的事件机制都提供了强大的支持和灵活性。希望本文能为您的开发工作提供实用的指导和帮助。
67 15
|
13天前
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
56 8
|
17天前
|
Java 开发者 Spring
Java Springboot监听事件和处理事件
通过这些内容的详细介绍和实例解析,希望能帮助您深入理解Spring Boot中的事件机制,并在实际开发中灵活应用,提高系统的可维护性和扩展性。
50 7
|
25天前
|
缓存 前端开发 Java
【Spring】——SpringBoot项目创建
SpringBoot项目创建,SpringBootApplication启动类,target文件,web服务器,tomcat,访问服务器
|
2月前
|
监控 Java 数据库连接
详解Spring Batch:在Spring Boot中实现高效批处理
详解Spring Batch:在Spring Boot中实现高效批处理
343 12
|
2月前
|
安全 Java 测试技术
详解Spring Profiles:在Spring Boot中实现环境配置管理
详解Spring Profiles:在Spring Boot中实现环境配置管理
121 10
|
1月前
|
负载均衡 Java 开发者
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
167 5