springboot 启动分析六
2018-10-21 本文已影响8人
0爱上1
承接启动分析五,本文继续探索springboot的启动之旅
该文主要分析上下文刷新完成之后做了哪些工作
public ConfigurableApplicationContext run(String... args) {
// 声明并实例化一个跑表,用于计算springboot应用程序启动时间
StopWatch stopWatch = new StopWatch();
// 启动跑表
stopWatch.start();
// 声明一个应用程序上下文,注意这里是一个接口声明
ConfigurableApplicationContext context = null;
// 声明一个集合,用于记录springboot异常报告
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 配置不在意的属性 java.awt.headless
configureHeadlessProperty();
// 获取用于监听spring应用程序run方法的监听器实例
SpringApplicationRunListeners listeners = getRunListeners(args);
// 循环启动用于run方法的监听器
listeners.starting();
try {
// 封装应用参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
// 根据SpringApplication实例化时候推断出来的应用类型 webApplicationType,
// 去获取不同的环境,然后获取配置要适用的PropertySource以及激活哪个Profile
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
// 根据环境配置需要忽略的bean的信息
configureIgnoreBeanInfo(environment);
// 根据环境配置打印banner,即根据bannerMode 枚举值,决定是否打印banner和banner打印的位置
Banner printedBanner = printBanner(environment);
// key 4 创建应用程序上下文,
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[]{ConfigurableApplicationContext.class}, context);
// key 5 准备应用上下文
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
// key 6 刷新上下文
refreshContext(context);
// key 7 处理刷新上下文之后的事情
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
// key 8 上下文启动完成发布事件
listeners.started(context);
// key 9
callRunners(context, applicationArguments);
} catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
// key 10
listeners.running(context);
} catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
key7 刷新之后 afterRefresh(context, applicationArguments)
这里其实方法是空的,没有作任何的事
protected void afterRefresh(ConfigurableApplicationContext context,
ApplicationArguments args) {
}
key 8 上下文刷新完成,应用程序已经启动,事件发布
但此时 CommandLineRunners和ApplicationRunners还没有被回调
public void started(ConfigurableApplicationContext context) {
context.publishEvent(
new ApplicationStartedEvent(this.application, this.args, context));
}
跟踪代码看到最后发布事件之前只有两个Listener感兴趣ApplicationStartedEvent事件
感兴趣ApplicationStartedEvent事件的监听器BackgroundPreinitializer
在耗时任务的后台线程中触发早期初始化
public void onApplicationEvent(SpringApplicationEvent event) {
if (event instanceof ApplicationStartingEvent
&& preinitializationStarted.compareAndSet(false, true)) {
performPreinitialization();
}
if ((event instanceof ApplicationReadyEvent
|| event instanceof ApplicationFailedEvent)
&& preinitializationStarted.get()) {
try {
preinitializationComplete.await();
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
可以看到这里两个if都没有进入
DelegatingApplicationListener
委托给其他监听器处理事件
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
List<ApplicationListener<ApplicationEvent>> delegates = getListeners(
((ApplicationEnvironmentPreparedEvent) event).getEnvironment());
if (delegates.isEmpty()) {
return;
}
this.multicaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener<ApplicationEvent> listener : delegates) {
this.multicaster.addApplicationListener(listener);
}
}
if (this.multicaster != null) {
this.multicaster.multicastEvent(event);
}
}
这里也没有作什么事情,继续往下看
key 9 callRunners
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
AnnotationAwareOrderComparator.sort(runners);
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}
-
从上下文中获取ApplicationRunner类型的bean,以及CommandLineRunner类型的bean
-
排序
-
依次调用其run方法,并传入相应的参数
private void callRunner(ApplicationRunner runner, ApplicationArguments args) { try { (runner).run(args); } catch (Exception ex) { throw new IllegalStateException("Failed to execute ApplicationRunner", ex); } } private void callRunner(CommandLineRunner runner, ApplicationArguments args) { try { (runner).run(args.getSourceArgs()); } catch (Exception ex) { throw new IllegalStateException("Failed to execute CommandLineRunner", ex); } }
至此,整个callRunners方法就分析完毕
key 10 listeners.running(context)
发布上下文ApplicationReadyEvent事件
public void running(ConfigurableApplicationContext context) {
context.publishEvent(
new ApplicationReadyEvent(this.application, this.args, context));
}
这里可以看到有三个监听器感兴趣该事件
ApplicationReadyEvent前两个事件分析过了,重点看一下第三个事件
ApplicationListenerMethodAdapter
public void onApplicationEvent(ApplicationEvent event) {
this.processEvent(event);
}
public void processEvent(ApplicationEvent event) {
Object[] args = this.resolveArguments(event);
if (this.shouldHandle(event, args)) {
Object result = this.doInvoke(args);
if (result != null) {
this.handleResult(result);
} else {
this.logger.trace("No result object given - no result to handle");
}
}
}
总结
通过前面几篇的springboot 启动分析,至此已经完成了整个启动过程