文章目录
一、前言
本文是 Spring源码分析:Spring源码分析六:Spring 的刷新 - refresh() 的衍生文章。主要是因为本人菜鸡,在分析源码的过程中还有一些其他的内容不理解,故开设衍生篇来完善内容以学习。
二、简单使用
- 自定义监听事件
public class DemoEvent extends ApplicationEvent {
private String msg;
public DemoEvent(Object source) {
super(source);
}
public DemoEvent(Object source, String msg) {
super(source);
this.msg = msg;
}
public void printMsg(){
System.out.println("msg = " + msg);
}
}
- 自定义监听器
@Component
public class DemoListener implements ApplicationListener<DemoEvent> {
@Override
public void onApplicationEvent(DemoEvent event) {
event.printMsg();
}
}
- 测试
@SpringBootApplication
public class SpringbootDemoApplication implements ApplicationRunner {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(SpringbootDemoApplication.class, args);
DemoEvent demoEvent = new DemoEvent("", "world");
run.publishEvent(demoEvent);
}
}
运行后看到如下:
当程序运行时,Spring 将会发出 DemoEvent 事件转给DemoListener 监听器,进行进一步的处理。
实际上,Spring是将所有的事件都发送给所有的监听者,这一点在后面的源码分析中可以看出来。
三、源码分析
整个监听事件的流程其实很简单
1. 初始化 事件广播器 - initApplicationEventMulticaster();
initApplicationEventMulticaster 的方法比较简单,考虑了两种情况
- 如果用户自定义了事件广播器,在使用用户自定义的事件广播器
- 如果用户没有自定义事件广播器,则使用默认的 ApplicationEventMulticaster
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);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
// 否则使用默认的事件广播器 SimpleApplicationEventMulticaster
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
上面的代码看起来很简单,一般情况下我们都是使用默认的事件广播器SimpleApplicationEventMulticaster
2. 注册监听器 - registerListeners();
protected void registerListeners() {
// Register statically specified listeners first.
// 硬编码方式注册的监听器处理
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
// 配置文件注册的监听处理器
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
// 发布一个早期的Application 事件
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
3. 事件的发布 - publishEvent
我们在 上面的Demo 中, 通过 run.publishEvent(demoEvent); 发布的事件最终会执行如下方法:
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// Decorate event as an ApplicationEvent if necessary
// 分析事件类型
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
// 获取事件广播器进行广播事件广播。我们上面说了一般我们使用默认的事件广播器即 SimpleApplicationEventMulticaster
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
// 寻找父类BeanFactory,继续发布消息
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
我们继续看 multicastEvent 方法如下,可以看到,当Spring事件产生的时候,默认会使用SimpleApplicationEventMulticaster#multicastEvent 方法来广播事件,遍历所有的监听器,并使用监听器中的 onApplicationEvent 方法来进行监听事件的处理。而对于每个监听器来说,其实都可以获取到产生的事件,但使用进行处理由监听器自己决定。
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
// 获取匹配事件类型的事件事件监听器。比如上面Demo中DemoListener 监听的是DemoEvent 事件类型,这里就是筛选出接受 DemoEvent 类型的监听器。
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
// 在invokeListener 方法中激活调用事件监听器的onApplicationEvent方法
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
以上:内容部分参考
《Spring源码深度解析》
如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正