简述
注册应用监听器,将所有ApplicationListener注册到ApplicationEventMulticaster中。
这是refresh()方法的第10步,在onRefresh之后、Bean实例化之前执行。
这一步会注册三类监听器:
1. 静态指定的监听器(通过代码添加)
2. 容器中已定义的ApplicationListener Bean
3. 发布早期事件(在多播器创建之前缓存的事件)
核心流程
- 注册静态指定的ApplicationListener
- 注册容器中ApplicationListener类型的Bean名称(还未实例化)
- 发布早期事件(earlyApplicationEvents)
- 清空早期事件集合
源码分析
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
/** 应用监听器集合 */
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
/** 早期应用监听器(refresh前的监听器) */
@Nullable
private Set<ApplicationListener<?>> earlyApplicationListeners;
/** 早期应用事件(多播器创建前的事件) */
@Nullable
private Set<ApplicationEvent> earlyApplicationEvents;
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// ... 前面的步骤
try {
// ... initMessageSource
// ... initApplicationEventMulticaster
// ... onRefresh
// 注册监听器
registerListeners();
// finishBeanFactoryInitialization
// ... 后续步骤
}
catch (BeansException ex) {
// 异常处理
}
}
}
protected void registerListeners() {
// 1. 首先注册静态指定的监听器
// 这些监听器是通过addApplicationListener方法添加的
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 2. 注册容器中ApplicationListener类型的Bean名称
// 注意:这里只注册Bean名称,不实例化Bean(懒加载)
// 实际的监听器Bean会在后面的finishBeanFactoryInitialization中实例化
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 3. 发布早期应用事件
// 这些事件是在ApplicationEventMulticaster创建之前发布的
// 在prepareRefresh中创建了earlyApplicationEvents集合来缓存这些事件
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null; // 清空,之后的事件直接发布
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
Assert.notNull(listener, "ApplicationListener must not be null");
if (this.applicationEventMulticaster != null) {
this.applicationEventMulticaster.addApplicationListener(listener);
}
this.applicationListeners.add(listener);
}
}
三类监听器
1. 静态指定的监听器
通过代码直接添加的监听器,在ApplicationContext创建时就已经存在:
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
// 添加静态监听器
app.addListeners(new ApplicationListener<ApplicationEvent>() {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("Event: " + event);
}
});
app.run(args);
}
}
SpringBoot在启动时会自动添加一些内置监听器:
- LoggingApplicationListener
- BackgroundPreinitializer
- DelegatingApplicationListener
- 等等
2. Bean定义的监听器
容器中定义的ApplicationListener Bean:
// 方式1:实现接口
@Component
public class MyListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("Context refreshed");
}
}
// 方式2:使用@EventListener注解
@Component
public class MyEventHandler {
@EventListener
public void handleContextRefreshed(ContextRefreshedEvent event) {
System.out.println("Context refreshed");
}
}
注意:在registerListeners阶段,这些监听器Bean还未实例化,只是将Bean名称注册到多播器。实际的实例化在finishBeanFactoryInitialization阶段。
3. 早期事件
在ApplicationEventMulticaster创建之前(initApplicationEventMulticaster步骤之前),如果有事件需要发布,会先缓存在earlyApplicationEvents集合中。
这些事件会在registerListeners阶段被重新发布。
为什么只注册Bean名称而不实例化?
// 只注册Bean名称
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
原因:
1. 保持Bean的生命周期一致性:所有普通Bean都在finishBeanFactoryInitialization阶段统一实例化
2. 避免依赖问题:监听器Bean可能依赖其他Bean,过早实例化可能导致依赖注入失败
3. 懒加载优化:如果某个监听器从未被触发,可以不实例化(取决于具体实现)
AbstractApplicationEventMulticaster的监听器管理
public abstract class AbstractApplicationEventMulticaster
implements ApplicationEventMulticaster {
/** 监听器检索器辅助类 */
private final ListenerRetriever defaultRetriever = new ListenerRetriever();
/** 监听器Bean的BeanFactory */
@Nullable
private BeanFactory beanFactory;
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
synchronized (this.defaultRetriever) {
// 如果是代理对象,移除原对象避免重复
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
if (singletonTarget instanceof ApplicationListener) {
this.defaultRetriever.applicationListeners.remove(singletonTarget);
}
this.defaultRetriever.applicationListeners.add(listener);
}
}
@Override
public void addApplicationListenerBean(String listenerBeanName) {
synchronized (this.defaultRetriever) {
this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);
}
}
/**
* 获取对指定事件感兴趣的所有监听器
*/
protected Collection<ApplicationListener<?>> getApplicationListeners(
ApplicationEvent event, ResolvableType eventType) {
Object source = event.getSource();
Class<?> sourceType = (source != null ? source.getClass() : null);
// 从缓存中查找
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
ListenerRetriever newRetriever = null;
// ... 缓存处理逻辑
// 检索匹配的监听器
return retrieveApplicationListeners(eventType, sourceType, newRetriever);
}
private Collection<ApplicationListener<?>> retrieveApplicationListeners(
ResolvableType eventType, @Nullable Class<?> sourceType,
@Nullable ListenerRetriever retriever) {
List<ApplicationListener<?>> allListeners = new ArrayList<>();
// 1. 处理已实例化的监听器
for (ApplicationListener<?> listener : this.defaultRetriever.applicationListeners) {
if (supportsEvent(listener, eventType, sourceType)) {
allListeners.add(listener);
}
}
// 2. 处理监听器Bean(需要时实例化)
if (!this.defaultRetriever.applicationListenerBeans.isEmpty()) {
BeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : this.defaultRetriever.applicationListenerBeans) {
try {
if (supportsEvent(beanFactory, listenerBeanName, eventType, sourceType)) {
// 从容器中获取监听器Bean(触发实例化)
ApplicationListener<?> listener =
beanFactory.getBean(listenerBeanName, ApplicationListener.class);
if (!allListeners.contains(listener)) {
allListeners.add(listener);
}
}
}
catch (NoSuchBeanDefinitionException ex) {
// 忽略:Bean可能已被删除
}
}
}
// 排序
AnnotationAwareOrderComparator.sort(allListeners);
return allListeners;
}
}
监听器的执行顺序
可以通过以下方式控制监听器的执行顺序:
1. 实现Ordered接口
@Component
public class FirstListener implements ApplicationListener<ContextRefreshedEvent>, Ordered {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("First listener");
}
@Override
public int getOrder() {
return 1; // 数字越小越先执行
}
}
@Component
public class SecondListener implements ApplicationListener<ContextRefreshedEvent>, Ordered {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("Second listener");
}
@Override
public int getOrder() {
return 2;
}
}
2. 使用@Order注解
@Component
@Order(1)
public class FirstListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("First listener");
}
}
@Component
@Order(2)
public class SecondListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("Second listener");
}
}
3. @EventListener with @Order
@Component
public class MyEventHandler {
@EventListener
@Order(1)
public void handleFirst(ContextRefreshedEvent event) {
System.out.println("First handler");
}
@EventListener
@Order(2)
public void handleSecond(ContextRefreshedEvent event) {
System.out.println("Second handler");
}
}
监听器的条件执行
可以使用SpEL表达式来条件性地执行监听器:
@Component
public class ConditionalEventHandler {
@EventListener(condition = "#event.success == true")
public void handleSuccessEvent(MyEvent event) {
System.out.println("Only handle success events");
}
@EventListener(condition = "#root.event.source.active")
public void handleActiveSourceEvent(MyEvent event) {
System.out.println("Only handle events from active sources");
}
}
早期事件的典型场景
早期事件通常是在ApplicationContext准备阶段发布的一些通知事件:
// 在prepareContext阶段
private void prepareContext(ConfigurableApplicationContext context, ...) {
// ...
// 发布ApplicationStartingEvent(这是早期事件)
listeners.contextPrepared(context);
// ...
}
SpringBoot的早期事件包括:
- ApplicationStartingEvent
- ApplicationEnvironmentPreparedEvent
- ApplicationContextInitializedEvent
- ApplicationPreparedEvent
参考调用栈
registerListeners:895, AbstractApplicationContext (org.springframework.context.support)
refresh:546, AbstractApplicationContext (org.springframework.context.support)
refresh:143, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
refresh:755, SpringApplication (org.springframework.boot)
refreshContext:402, SpringApplication (org.springframework.boot)
run:312, SpringApplication (org.springframework.boot)