springboot源码----EventPublishingRunListener
EventPublishingRunListener 类实现了SpringApplicationRunListener接口,那么在springboot启动的过程中都会对这个类进行回调通知,那么通知什么? 其实看源码可以看出来里面对所有通知其实都是回调了ApplicationListener接口,说白了就是他就是一个ApplicationListener的代理。springboot启动的几个主要过程的监听通知都是通过他来进行回调
首先看下starting方法:
@Override
public void starting() {
this.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
}
第一步调用了SimpleApplicationEventMulticaster类的multicastEvent方法并且传入了ApplicationStartingEvent对象。
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
紧接着遍历了每个事件是ApplicationStartingEvent的监听器
@SuppressWarnings({"unchecked", "rawtypes"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass().getName())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
最后进行回调
这边有几个问题:
- EventPublishingRunListener是什么时候初始化的
- SimpleApplicationEventMulticaster类里面的ApplicationListener实现类是怎么来的
这边主要看下EventPublishingRunListener的构造器:
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
this.initialMulticaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
这边可以看出来在EventPublishingRunListener初始化的时候会把SpringApplication带进来,而SpringApplication的对象中就有ApplicationListener的实现类 实在ApplicationListener初始化的时候生成的。
注意下contextLoaded方法
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
for (ApplicationListener> listener : this.application.getListeners()) {
if (listener instanceof ApplicationContextAware) {
((ApplicationContextAware) listener).setApplicationContext(context);
}
context.addApplicationListener(listener);
}
this.initialMulticaster.multicastEvent(
new ApplicationPreparedEvent(this.application, this.args, context));
}
这边这个方法比前面的方法特殊了一点,前面的方法直接调用this.initialMulticaster.multicastEvent就结束了。这边还做了另外两件事
- 1 遍历了SpringApplication中所有的ApplicationListener实现类,如果有实现类还实现了ApplicationContextAware接口 就把上下文给其设置进去
- 2 将这些 ApplicationListener实现类全部加入到上下文中(这个大家应该比较属性我们实现自己的监听的时候也会这么做)
然后在这个之后的方法就全部通过context.publishEvent来进行回调
【springboot源码----EventPublishingRunListener】这也不难理解 因为只有到了contextLoaded方法之后才有了上下 之前还没有上下文所以只能通过SimpleApplicationEventMulticaster类进行回调所有的ApplicationListener实现类
推荐阅读
- Activiti(一)SpringBoot2集成Activiti6
- SpringBoot调用公共模块的自定义注解失效的解决
- 解决SpringBoot引用别的模块无法注入的问题
- Android事件传递源码分析
- Quartz|Quartz 源码解析(四) —— QuartzScheduler和Listener事件监听
- [源码解析]|[源码解析] NVIDIA HugeCTR,GPU版本参数服务器---(3)
- ffmpeg源码分析01(结构体)
- Java程序员阅读源码的小技巧,原来大牛都是这样读的,赶紧看看!
- springboot使用redis缓存
- Vue源码分析—响应式原理(二)