spring boot 事件(ApplicationEventMulticaster)

本文概述了SpringBoot应用程序从启动到运行过程中的一系列事件,包括ApplicationStartingEvent、ApplicationEnvironmentPreparedEvent、ApplicationContextInitializedEvent等,并详细介绍了每个事件的触发时机及处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

应用程序事件在您的应用程序运行时按以下顺序发送:

  1. ApplicationStartingEvent 创建完成SpringApplication对象后执行SpringApplicationRunListeners.starting,发送一个ApplicationStartingEvent 事件到广播器SimpleApplicationEventMulticaster,SimpleApplicationEventMulticaster将遍历所有的listeners,触发所有支持ApplicationStartingEvent 事件的监听器。
EventPublishingRunListener:
public void starting() {
    this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}
  1. ApplicationEnvironmentPreparedEvent, Environment配置完成后,发送一个ApplicationEnvironmentPreparedEvent事件到广播器SimpleApplicationEventMulticaster,触发所有支持ApplicationEnvironmentPreparedEvent事件的监听器。ApplicationContextInitializedEvent
EventPublishingRunListener:
public void environmentPrepared(ConfigurableEnvironment environment) {
    this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
}
  1. ApplicationContextInitializedEvent,在ApplicationContext准备好且已调用ApplicationContextInitializers之后但未加载任何bean定义之前,发送ApplicationContextInitializedEvent事件到广播器SimpleApplicationEventMulticaster,触发所有支持ApplicationContextInitializedEvent事件的监听器。
public void contextPrepared(ConfigurableApplicationContext context) {
    this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
}
  1. ApplicationPreparedEvent,在刷新开始之前但在加载系统和主函数bean定义之后,bean class loader 创建之后发送一个ApplicationPreparedEvent事件到广播器SimpleApplicationEventMulticaster,触发所有支持ApplicationPreparedEvent事件的监听器。
public void contextLoaded(ConfigurableApplicationContext context) {
    ApplicationListener listener;
    for(Iterator var2 = this.application.getListeners().iterator(); var2.hasNext(); context.addApplicationListener(listener)) {
        listener = (ApplicationListener)var2.next();
        if (listener instanceof ApplicationContextAware) {
            ((ApplicationContextAware)listener).setApplicationContext(context);
        }
    }

    this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}
  1. ApplicationStartedEvent上下文已被刷新后,但是任何应用程序和Runner被调用前,发送一个ApplicationStartedEvent事件到广播器SimpleApplicationEventMulticaster,触发所有支持ApplicationStartedEvent事件的监听器,紧接着
    AvailabilityChangeEvent其后发送的LivenessState.CORRECT,表示该应用程序被视为已生效。
public void started(ConfigurableApplicationContext context) {
    context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
    AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
}
  1. ApplicationReadyEvent, Runner被调用后发送一个ApplicationReadyEvent事件到广播器SimpleApplicationEventMulticaster,触发所有支持ApplicationReadyEvent事件的监听器,。紧随AvailabilityChangeEvent其后发送,ReadinessState.ACCEPTING_TRAFFIC以指示该应用程序已准备好处理请求。
public void running(ConfigurableApplicationContext context) {
    context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
    AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
}
  1. ApplicationFailedEvent,在启动时异常发送ApplicationFailedEvent事件到广播器SimpleApplicationEventMulticaster,触发所有支持ApplicationFailedEvent事件的监听器
public void failed(ConfigurableApplicationContext context, Throwable exception) {
    ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception);
    if (context != null && context.isActive()) {
        context.publishEvent(event);
    } else {
        if (context instanceof AbstractApplicationContext) {
            Iterator var4 = ((AbstractApplicationContext)context).getApplicationListeners().iterator();

            while(var4.hasNext()) {
                ApplicationListener<?> listener = (ApplicationListener)var4.next();
                this.initialMulticaster.addApplicationListener(listener);
            }
        }

        this.initialMulticaster.setErrorHandler(new EventPublishingRunListener.LoggingErrorHandler());
        this.initialMulticaster.multicastEvent(event);
    }

}

上面的列表仅包含SpringApplicationEvent与绑定的SpringApplication。除这些以外,以下事件也在ApplicationPreparedEvent之后和ApplicationStartedEvent之前发布:

  • web server准备就绪后发送一个WebServerInitializedEvent事件,此事件是在org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle.start()方法中启动server后调用AbstractApplicationContext.publishEvent发布事件。
org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle
class WebServerStartStopLifecycle implements SmartLifecycle {
    private final ServletWebServerApplicationContext applicationContext;
    private final WebServer webServer;
    private volatile boolean running;

    WebServerStartStopLifecycle(ServletWebServerApplicationContext applicationContext, WebServer webServer) {
        this.applicationContext = applicationContext;
        this.webServer = webServer;
    }

    public void start() {
        this.webServer.start();
        this.running = true;
        this.applicationContext.publishEvent(new ServletWebServerInitializedEvent(this.webServer, this.applicationContext));
    }

    public void stop() {
        this.webServer.stop();
    }

    public boolean isRunning() {
        return this.running;
    }

    public int getPhase() {
        return 2147483646;
    }
}
  • ReactiveWebServerInitializedEvent是servlet的反应式编程,此事件是在org.springframework.boot.web.reactive.context.WebServerStartStopLifecycle.start里发出的。
org.springframework.boot.web.reactive.context.WebServerStartStopLifecycle:
class WebServerStartStopLifecycle implements SmartLifecycle {
    private final WebServerManager weServerManager;
    private volatile boolean running;

    WebServerStartStopLifecycle(WebServerManager weServerManager) {
        this.weServerManager = weServerManager;
    }

    public void start() {
        this.weServerManager.start();
        this.running = true;
    }

    public void stop() {
        this.running = false;
        this.weServerManager.stop();
    }

    public boolean isRunning() {
        return this.running;
    }

    public int getPhase() {
        return 2147483646;
    }
}
org.springframework.boot.web.reactive.context.WebServerManager
class WebServerManager {
    private final ReactiveWebServerApplicationContext applicationContext;
    private final WebServerManager.DelayedInitializationHttpHandler handler;
    private final WebServer webServer;

    WebServerManager(ReactiveWebServerApplicationContext applicationContext, ReactiveWebServerFactory factory, Supplier<HttpHandler> handlerSupplier, boolean lazyInit) {
        this.applicationContext = applicationContext;
        Assert.notNull(factory, "Factory must not be null");
        this.handler = new WebServerManager.DelayedInitializationHttpHandler(handlerSupplier, lazyInit);
        this.webServer = factory.getWebServer(this.handler);
    }

    void start() {
        this.handler.initializeHandler();
        this.webServer.start();
        this.applicationContext.publishEvent(new ReactiveWebServerInitializedEvent(this.webServer, this.applicationContext));
    }

    void shutDownGracefully(Runnable callback) {
        this.webServer.shutDownGracefully((result) -> {
            callback.run();
        });
    }

    void stop() {
        this.webServer.stop();
    }

    WebServer getWebServer() {
        return this.webServer;
    }

    HttpHandler getHandler() {
        return this.handler;
    }
    ......
  }
<think>嗯,用户问的是关于Spring框架中事件监听器的使用方法、示例教程和最佳实践。首先,我需要回忆一下Spring事件机制的基本概念和相关组件。记得Spring事件监听是基于观察者模式,主要涉及ApplicationEvent、ApplicationListener、ApplicationEventPublisher这几个核心类。用户可能需要一个从创建事件到监听再到发布的完整流程,所以得按照步骤来讲解。 首先,创建自定义事件,应该继承ApplicationEvent类。比如用户定义的OrderCreatedEvent,里面包含订单ID。这一步挺直接的,但要注意构造方法里调用super(source),可能需要传递事件源。 然后是事件监听器,有两种方式:实现ApplicationListener接口或者使用@EventListener注解。用注解的话更灵活,方法名可以自定义,而且不需要指定事件类型,Spring会自动识别。可能用户会更倾向于注解方式,因为更简洁,代码侵入性低。 接下来是发布事件,需要用ApplicationEventPublisher,可以通过ApplicationContext自动注入,或者实现ApplicationEventPublisherAware接口。在服务层调用publishEvent方法触发事件,这一步需要确保发布器的正确注入,否则事件发不出去。 示例配置部分,用户可能用的是Spring Boot,所以配置类需要加上@EnableAsync或者其他相关注解吗?比如异步事件处理的话,可能需要配置任务执行器,但用户的问题可能还没到那个深度。不过最佳实践里提到异步处理,应该简单说明一下,避免阻塞主线程。 运行示例的时候,通过CommandLineRunner来触发业务逻辑,调用服务层方法,这样就会发布事件,监听器就能捕获到。这里可能需要提醒用户注意事件的同步或异步处理方式,影响执行顺序。 最佳实践方面,除了异步,还有作用域的问题。比如在Web应用中,监听器的作用域需要和请求一致,可能要用到@Scope注解。另外异常处理也很重要,避免事件处理失败影响主流程。还有事件命名要有意义,结构清晰,方便维护。 关于引用,用户提供的引用中有提到ApplicationEventMulticaster事件注册表,这些可能属于内部机制,用户不一定需要深入,但可以稍微提一下,增强回答的可信度。比如引用[2]里提到SimpleApplicationEventMulticaster默认实现,可以说明Spring内部如何管理监听器。 可能需要生成的相关问题包括事件监听的原理、如何异步处理、与观察者模式的关系,以及实际应用场景。这些问题有助于用户进一步学习,符合用户的需求层次。 检查一下步骤是否正确,有没有遗漏的部分。比如创建事件、监听器、发布事件,这三个核心步骤是否都涵盖了。示例代码是否正确,特别是注解方式是否用了@EventListener,还有发布事件的方法是否正确调用了publishEvent。 另外,用户提供的引用中有提到初始化逻辑在AbstractApplicationContext的refresh方法里,这可能涉及到Spring容器的启动过程,但用户可能不需要知道这么底层,所以不用深入,但可以作为原理部分的问题生成。 确保回答符合系统级指令,数学公式用$...$,但这个问题里可能用不到数学公式,所以没问题。结构清晰,分步骤讲解,代码示例用正确的格式,引用标识放在相关段落后面。 最后,生成的相关问题要围绕Spring事件监听的扩展,比如原理、优化、应用场景等,帮助用户深入理解。确保没有错误,比如引用编号是否正确对应,比如引用[^1]到[^5]是否正确关联到用户给的引用内容。</think>### Spring框架事件监听器使用教程 #### 一、核心组件 Spring事件监听机制基于**观察者模式**,包含以下核心组件: 1. **ApplicationEvent**:自定义事件的基类 2. **ApplicationListener**:事件监听器接口 3. **ApplicationEventPublisher**:事件发布接口 #### 二、使用步骤 1. **创建自定义事件** ```java public class OrderCreatedEvent extends ApplicationEvent { private String orderId; public OrderCreatedEvent(Object source, String orderId) { super(source); this.orderId = orderId; } // Getter省略 } ``` 2. **创建事件监听器** **方式1:实现接口** ```java @Component public class OrderEventListener implements ApplicationListener<OrderCreatedEvent> { @Override public void onApplicationEvent(OrderCreatedEvent event) { System.out.println("收到订单创建事件:" + event.getOrderId()); } } ``` **方式2:使用注解(推荐)** ```java @Component public class AnnotationOrderListener { @EventListener public void handleOrderEvent(OrderCreatedEvent event) { System.out.println("注解方式处理事件:" + event.getOrderId()); } } ``` 3. **发布事件** ```java @Service public class OrderService { @Autowired private ApplicationEventPublisher publisher; public void createOrder(String orderId) { // 业务逻辑 publisher.publishEvent(new OrderCreatedEvent(this, orderId)); } } ``` #### 三、配置示例(Spring Boot) ```java @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean public CommandLineRunner demo(OrderService service) { return args -> service.createOrder("20230815-001"); } } ``` #### 四、最佳实践 1. **异步事件处理** ```java @Configuration @EnableAsync public class AsyncConfig implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.initialize(); return executor; } } @EventListener @Async public void asyncHandleEvent(OrderCreatedEvent event) { // 异步处理逻辑 } ``` 2. **作用域控制** ```java @EventListener @Scope("request") public void handleRequestScopedEvent(OrderCreatedEvent event) { // 处理请求作用域事件 } ``` 3. **异常处理** ```java @EventListener public void handleEventWithFallback(OrderCreatedEvent event) { try { // 业务逻辑 } catch (Exception e) { // 记录日志并发送补偿事件 eventPublisher.publishEvent(new OrderFailedEvent(event)); } } ``` [^1]: Spring事件机制通过定义明确的事件传播流程保证可靠性 [^2]: 默认使用SimpleApplicationEventMulticaster进行事件广播 [^3]: 实际项目建议结合Gradle进行依赖管理 [^4]: 监听器注册后会自动关联到对应事件类型
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值