商城首页欢迎来到中国正版软件门户

您的位置:首页 >Spring监听器之ApplicationListener原理及源码深度解析

Spring监听器之ApplicationListener原理及源码深度解析

  发布于2026-04-27 阅读(0)

扫一扫,手机访问

一、原理及源码解析

在Spring框架中,事件驱动模型是一个核心但常被忽视的机制。它主要围绕几个关键事件展开:ContextRefreshedEvent、开发者自定义发布的事件(如示例中的IOCTest_Ext$1[source=我发布的事件]),以及ContextClosedEvent

那么,这些事件是如何产生并被处理的呢?我们不妨深入到源码层面,一探究竟。

事件的生命周期与触发时机

  • ContextRefreshedEvent事件:它的诞生与容器的生命周期紧密相连。
    1. 容器在创建对象时,会调用核心的refresh()方法。
    2. refresh()流程执行完毕,即容器刷新完成时,会通过finishRefresh()方法发布ContextRefreshedEvent事件。
  • 自定义发布事件:开发者可以在任何业务逻辑中,通过applicationContext.publishEvent()主动发布事件。
  • ContextClosedEvent事件:当容器关闭时,会自动发布此事件。

【事件发布流程】源码执行流程

当调用publishEvent(new ContextRefreshedEvent(this));时,幕后发生了什么?

  1. 获取事件派发器:首先,Spring会通过getApplicationEventMulticaster()获取事件的多播器(或称派发器)。
  2. 派发事件:接着,调用multicastEvent来派发事件。
  3. 获取监听器:派发器会获取所有与当前事件匹配的ApplicationListener。这个过程大致如下:
    for (final ApplicationListener listener : getApplicationListeners(event, type)) {
    1. 异步派发支持:如果配置了Executor,Spring会使用它进行异步派发,提升性能。
    2. 同步执行:如果没有配置Executor,则采用同步方式,直接调用invokeListener(listener, event);。最终,会回调监听器的onApplicationEvent方法。

【事件多播器(派发器)】源码执行流程

这个关键的派发器又是如何初始化的呢?

  1. 同样始于容器的refresh()方法。
  2. initApplicationEventMulticaster()方法中,Spring会初始化ApplicationEventMulticaster
    1. 它会先去容器中查找是否存在id="applicationEventMulticaster"的组件。
    2. 如果找不到,Spring会创建一个默认的SimpleApplicationEventMulticaster(beanFactory)实例,并将其注册到容器中。这样一来,其他需要派发事件的组件就能自动注入这个多播器了。

【容器中有哪些监听器】源码执行流程

监听器又是如何被收集并注册到派发器中的?

  1. 依旧是refresh()方法。
  2. registerListeners()阶段,Spring会从容中找出所有类型为ApplicationListener的Bean。
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    //将listener注册到ApplicationEventMulticaster中
    getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);

SmartInitializingSingleton 原理

除了事件监听,还有一个与之相关的接口SmartInitializingSingleton,其核心方法是afterSingletonsInstantiated()。它的执行时机是:

  1. IoC容器创建对象并执行refresh()
  2. finishBeanFactoryInitialization(beanFactory)阶段,初始化所有剩余的单例Bean。
    1. 首先,创建所有的单实例Bean(调用getBean())。
    2. 然后,遍历所有创建好的单例Bean,判断其是否实现了SmartInitializingSingleton接口。如果是,则调用其afterSingletonsInstantiated()方法。

二、实例

理论说得再多,不如动手一试。ApplicationListener是监听容器中发布事件的核心接口,它正是Spring事件驱动模型开发的基石。

该接口定义为:public interface ApplicationListener,意味着它可以监听ApplicationEvent及其所有子类事件。

使用起来,通常遵循以下几个步骤:

  1. 编写监听器:创建一个类来实现ApplicationListener接口,或者更简单地,在任意Bean的方法上使用@EventListener注解。后者的原理在于,Spring容器中有一个EventListenerMethodProcessor处理器,专门负责解析方法上的这个注解。
  2. 纳入容器管理:通过@Component@Service等注解,将监听器类装配到Spring容器中。
  3. 监听事件:只要容器中发布了相关事件,注册的监听器就能自动监听到。例如:
    • ContextRefreshedEvent:当容器刷新完成,所有Bean都完全创建后发布。
    • ContextClosedEvent:当容器关闭时发布。
  4. 发布事件:在任何可以获取到ApplicationContext的地方,调用applicationContext.publishEvent()方法,即可发布自定义事件。

1、自定义监听器

首先,我们可以定义一个实现ApplicationListener接口的类。这样,它就能监听所有类型的ApplicationEvent。别忘了用@Component将其装配到Spring容器中。

package com.atguigu.ext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class MyApplicationListener implements ApplicationListener {
	//当容器中发布此事件以后,方法触发
	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		// TODO Auto-generated method stub
		System.out.println("收到事件:"+event);
	}
}

另一种更灵活的方式是使用@EventListener注解。你可以将它标注在任何一个Bean的方法上。注意,@EventListener(classes={ApplicationEvent.class})中的classes属性可以指定多个要监听的类,用逗号分隔即可。

package com.atguigu.ext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class UserService {
	@EventListener(classes={ApplicationEvent.class})
	public void listen(ApplicationEvent event){
		System.out.println("UserService。。监听到的事件:"+event);
	}
}

2、定义配置类,加载IOC容器

接下来,需要一个配置类来扫描并加载这些组件。

@ComponentScan("com.atguigu.ext")
@Configuration
public class ExtConfig {
	@Bean
	public Blue blue(){
		return new Blue();
	}
}

3、测试

最后,我们编写测试代码来验证。在测试中,我们不仅会触发Spring内置的容器刷新和关闭事件,还会主动发布一个自定义事件(这里使用了匿名内部类来创建ApplicationEvent)。

package com.atguigu.test;
import org.junit.Test;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.atguigu.ext.ExtConfig;
public class IOCTest_Ext {
	@Test
	public void test01(){
		AnnotationConfigApplicationContext applicationContext  = new AnnotationConfigApplicationContext(ExtConfig.class);
		//发布事件;
		applicationContext.publishEvent(new ApplicationEvent(new String("我发布的事件")) {
		});
		applicationContext.close();
	}
}

运行结果:

Spring监听器之ApplicationListener原理及源码深度解析

Spring监听器之ApplicationListener原理及源码深度解析

结果说明:从控制台输出可以清晰看到,Spring容器自身在刷新和关闭时会发布事件,这些事件被我们自定义的监听器成功捕获。同时,我们主动发布的那个自定义事件“我发布的事件”,也同样被监听到了。这充分证明了,无论是Spring内置的事件,还是开发者自定义的事件,只要监听器注册得当,整个事件驱动模型就能顺畅运转。

本文转载于:https://www.jb51.net/program/362537s4d.htm 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注