在启动流程中,会出发许多ApplicationEvent。这时会调用对应的listener的onApplicationEvent方法。ApplicationEvent时观察者模式,
(1) 实体继承ApplicationEvent
(2) 注入的Listener 实现接口ApplicationListener, 触发后的处理逻辑在onApplicationnEvent中
(3) 事件发起方通过ApplicationContext 实例的publishEvent方法将 (1)的实体传入(2)
SpringBoot 启动时的入口方法SpringApplication.run 内部实现为
public static ConfigurableApplicationContext run(Class<?>[] primarySources,
String[] args) {
return new SpringApplication(primarySources).run(args);
}
第一步 new SpringApplication 内部会注入系统Listener 具体的listeners参见 https://blog.csdn.net/zl1zl2zl3/article/details/79765725
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
第二步 调用 run(args) 启动Listener
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
第二步 2.1 如何获取监听器:在getRunListeners中会读取配置文件,加载的是Springboot META-INF/spring.factories 中的 org.springframework.boot.context.event.EventPublishingRunListener, 并生成"事件发布启动监听器"的工厂实例
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
}
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, new Class<?>[] {});
}
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// 使用Set确保的字符串的唯一性
Set<String> names = new LinkedHashSet<String>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));// 1.载入工厂名称集合
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,// 2.创建工厂实例
classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);// 排序
return instances;
}
META-INF/spring.factories
# Run Listeners 这里呢,看这里!!!!
org.springframework.boot.SpringApplicationRunListener=
org.springframework.boot.context.event.EventPublishingRunListener
第二步 2.2 启动监听 starting()
SpringApplicationRunListeners listeners = this.getRunListeners(args);
//如果有监听器监听启动事件,则执行对应的动作
listeners.starting();
当前监听是EventPublishingRunListener,starting 方法如下
public void starting() {
this.initialMulticaster
.multicastEvent(new ApplicationStartedEvent(this.application, this.args));
}
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
invokeListener(listener, event);
}
}
}