Spring ApplicationContext(八)事件监听机制

时间:2022-05-03 13:50:31

Spring ApplicationContext(八)事件监听机制

本节则重点关注的是 Spring 的事件监听机制,主要是第 8 步:多播器注册;第 10 步:事件注册。

public void refresh() throws BeansException, IllegalStateException {
// 8. 注册多播器,事件监听器的管理者
initApplicationEventMulticaster();
// 9. 专门留给子类初始化其它 bean 用,这是一个空的方法
onRefresh();
// 10. 注册监听器
registerListeners();
}

事件定义如下,实现了 JDK 的规范 EventListener

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
// 监听 event 事件
void onApplicationEvent(E event);
}

一、ApplicationListener 实战

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component; @Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> { @Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("接收的事件:" + event);
}
}

运行后结果如下:

接收的事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.support.ClassPathXmlApplicationContext@16eabae: startup date [Sun Jul 29 12:41:42 CST 2018]; root of context hierarchy]

二、ApplicationEventMulticaster 多播器的初始化

ApplicationContext 中 refresh() 第 8 步 initApplicationEventMulticaster() 进行多播器的初始化工作

源代码【AbstractApplicationContext】

protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}

三、ApplicationListener 注册

ApplicationContext 中 refresh() 第 10 步 registerListeners() 进行事件监听者的注册工作。

源代码【AbstractApplicationContext】

protected void registerListeners() {
// 1. 注册静态指定的侦听器
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
} // 2. 注册 ApplicationListener
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
} // 3. Publish early application events
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}

四、ApplicationEvent 事件发布

源代码【AbstractApplicationContext】

public void publishEvent(ApplicationEvent event) {
publishEvent(event, null);
} public void publishEvent(Object event) {
publishEvent(event, null);
} protected void publishEvent(Object event, ResolvableType eventType) {
Assert.notNull(event, "Event must not be null"); // 1. 如果 event 不是 ApplicationEvent,则需要进行封装成 PayloadApplicationEvent
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<Object>(this, event);
if (eventType == null) {
eventType = ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass());
}
} // 2. 发布事件 event,如果多播器懒加载,还没有初始化则将该事件先放到 earlyApplicationEvents 容器中
// 等待多播器创建好了再发布事件 ???
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
} // 3. 父容器中也需要发布该事件 event
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}

每天用心记录一点点。内容也许不重要,但习惯很重要!