SpringBoot版本:2.1.1 ==》启动流程分析汇总
接上篇博客Spring Boot 2.1.1(十二)启动流程分析之创建应用上下文AnnotationConfigServletWebServerApplicationContext
目录
3、发布ApplicationContextInitializedEvent事件
6、发布ApplicationPreparedEvent事件
public ConfigurableApplicationContext run(String... args) {
....
try {
//本篇内容从本行开始记录
//getSpringFactoriesInstances这个就是得到该接口的实现类对象集合,见过跟多次,不多讲了,第二个参数是构造方法的参数
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//本篇内容记录到这,后续更新
....
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
}
流程分析
得到异常报告接口实现类对象集合就不讲了,前面看见过很多次了。至于实例化的时候构造方法中做了什么事情,简单截图看下代码,SpringBootExceptionReporter接口的实现类只有一个,就是FailureAnalyzers。
在构造方法中loadFailureAnalyzers方法会去加载FailureAnalyzer接口的实现类(META-INF/spring.factories),得到实例对象,又是持有一个FailureAnalyzer实例对象的集合,然后下面循环调用它们的analyze方法,跟前面说的那个很像,不知道是不是观察者模式,不深究了....
然后prepareFailureAnalyzers方法会去判断是否实现了BeanFactoryAware、EnvironmentAware,实现了则调用对应接口方法。
其中NoSuchBeanDefinitionFailureAnalyzer实现了BeanFactoryAware接口,在setBeanFactory方法中会注册一个ConditionEvaluationReport,这是第一次注册这个bean,该类用来记录状态信息用于日志输出,在后面还会用到。
讲下面这个方法,prepareContext().
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//设置环境,包括上下文环境,以及AnnotatedBeanDefinitionReader中的ConditionEvaluator对象的环境
//和ClassPathScanningCandidateComponentProvider的环境
context.setEnvironment(environment);
//对应用进行后置处理
postProcessApplicationContext(context);
//调用创建SpringApplication对象的时候得到的ApplicationContextInitializer接口实现类对象的Initializer方法
applyInitializers(context);
//发布ApplicationContextInitializedEvent事件
listeners.contextPrepared(context);
//日志输出
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
//得到BeanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//注册一个单例bean,名字是springApplicationArguments
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
//如果printedBanner 不为空,注册成单例bean
if (printedBanner != null) {
beanFactory.registerSingleton("s