spring boot 各种事件贯穿整个启动的生命周期,读懂了这些事件也差不多理解了springboot的启动流程。
SpringApplicationRunListener中的事件
接口org.springframework.boot.SpringApplicationRunListener
定义了spring启动过程中各个事件被触发的顶层方法
public interface SpringApplicationRunListener {
default void starting() {
}
default void environmentPrepared(ConfigurableEnvironment environment) {
}
default void contextPrepared(ConfigurableApplicationContext context) {
}
default void contextLoaded(ConfigurableApplicationContext context) {
}
default void started(ConfigurableApplicationContext context) {
}
default void running(ConfigurableApplicationContext context) {
}
default void failed(ConfigurableApplicationContext context, Throwable exception) {
}
}
SpringApplicationRunListener
的方法定义很讲究,方法从上到下的顺序也正好是各事件触发的顺序。SpringApplicationRunListener
接口的唯一具体实现类是org.springframework.boot.context.event.EventPublishingRunListener
。
starting
接口表示springboot程序准备开始启动,这是最早的事件触发方法,它将触发ApplicationStartingEvent
事件。这个事件一般没人关心,目前spring中没有任何逻辑实现依赖于这个事件。
//EventPublishingRunListener
@Override
public void starting() {
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}
environmentPrepared
接口方法表示Environment对象准备好了,它将触发ApplicationEnvironmentPreparedEvent
事件.
//EventPublishingRunListener
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster
.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
}
不论是本地配置文件还是云端配置中心,它们的配置内容读取都依赖于此事件。
ConfigFileApplicationListener
本地配置文件监听器
public class ConfigFileApplicationListener implements EnvironmentPostProcessor, SmartApplicationListener, Ordered{
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(eventType)
|| ApplicationPreparedEvent.class.isAssignableFrom(eventType);
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
}
if (event instanceof ApplicationPreparedEvent) {
onApplicationPreparedEvent(event);
}
}
}
BootstrapApplicationListener
云端配置中心监听器
public class BootstrapApplicationListener
implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
}
contextPrepared
表示ApplicationContext实例化后,所有的ApplicationContextInitializer
实例的initialize
已经被依次调用执行完毕。
这个方法将触发ApplicationContextInitializedEvent事件
//EventPublishingRunListener
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
this.initialMulticaster
.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
}
contextLoaded
方法表示ApplicationContext的各种资源已经被读取加载完毕(主要是各种BeanDefination的读取),但还没有进行上下文刷新。此方法将触发ApplicationPreparedEvent
事件
//EventPublishingRunListener
@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));
}
started
表示ApplicationContext的refresh
刷新完成,但CommandLineRunners
、ApplicationRunner
这些函数接口还未执行。
//EventPublishingRunListener
@Override
public void started(ConfigurableApplicationContext context) {
context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
}
running
方法表示CommandLineRunners
、ApplicationRunner
函数接口也都被调用执行完毕,它是springboot正常启动过程中的最后一个事件,它标志着项目已完全启动,它将触发ApplicationReadyEvent
事件。
//EventPublishingRunListener
@Override
public void running(ConfigurableApplicationContext context) {
context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
}
failed
表示项目启动过程中出现异常,启动过程中的任意一阶段都可能出错。
//EventPublishingRunListener
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception);
if (context != null && context.isActive()) {
// Listeners have been registered to the application context so we should
// use it at this point if we can
context.publishEvent(event);
}
else {
// An inactive context may not have a multicaster so we use our multicaster to
// call all of the context's listeners instead
if (context instanceof AbstractApplicationContext) {
for (ApplicationListener<?> listener : ((AbstractApplicationContext) context)
.getApplicationListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
this.initialMulticaster.setErrorHandler(new LoggingErrorHandler());
this.initialMulticaster.multicastEvent(event);
}
}
其他事件
ApplicationContext在刷新完成后,生命周期处理器的默认实现类DefaultLifecycleProcessor
的onRefresh方法会被调用,并发布ContextRefreshedEvent
事件。
DefaultLifecycleProcessor.onRefresh
会调用所有实现SmartLifecycle
接口的Spring Bean对象的start
方法。
//DefaultLifecycleProcessor
@Override
public void onRefresh() {
startBeans(true);
this.running = true;
}
private void startBeans(boolean autoStartupOnly) {
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new HashMap<>();
lifecycleBeans.forEach((beanName, bean) -> {
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
int phase = getPhase(bean);
LifecycleGroup group = phases.get(phase);
if (group == null) {
group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
phases.put(phase, group);
}
group.add(beanName, bean);
}
});
if (!phases.isEmpty()) {
List<Integer> keys = new ArrayList<>(phases.keySet());
Collections.sort(keys);
for (Integer key : keys) {
phases.get(key).start();
}
}
}
WebServerStartStopLifecycle
也实现了SmartLifecycle
接口,此start
方法将启动Tomcat容器,并发布ServletWebServerInitializedEvent
事件。