创建SpringApplication对象
1.启动类中会调用SpringApplication中的静态run方法创建SpringApplication对象
,并调用SpringApplication的run方法
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
2.创建SpringApplication对象
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
//保存主启动类到set集合中,可以是多个
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
/** 判断Application类型,后续会根据该参数选择ApplicationContext容器,主要有三种
*1.NONE:作为非web应用启动
*2.SERVLET:基于servlet的web应用
*3.REACTIVE: 作为一个reactive的web应用
*/
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//加载并创建springfactories文件中BootstrapRegistryInitializer的所有实现类的实例对象
this.bootstrapRegistryInitializers = new ArrayList<>(getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
//加载springfactories文件中的所有实现类,并放入到缓存中。后续加载直接从缓存中读取
//返回springfactories文件中ApplicationContextInitializer所有实现类对象
setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class));
//加载springfactories文件中ApplicationListener所有实现类
setListeners((Collection)getSpringFactoriesInstances(ApplicationListener.class));
//得到根据main方法得到主类
this.mainApplicationClass = deduceMainApplicationClass();
}
环境准备
SpringBootExceptionReporter 异常分析器
使用java的spi机制,从springfactories文件中获取实现类(因为前面已经将其放入缓存中,所以可以直接从缓存中获取)。SpringBootExceptionReporter接口对应实现类FailureAnalyzers
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = (Map)cache.get(classLoader);
if (result != null) {
return result;
} else {
初始化FailureAnalyzers时,会先将FailureAnalyzer的所有继承类从缓存中读取,同样使用了java的spi机制。
FailureAnalyzers(ConfigurableApplicationContext context) {
this(context, SpringFactoriesLoader.loadFactoryNames(FailureAnalyzer.class, getClassLoader(context)));
}
之后再将初始化完成的所有异常分析器(FailureAnalyzer的所有继承类)放入FailureAnalyzer成员变量中。同时判断所有异常分析器是否实现BeanFactoryAware,EnvironmentAware接口。如果实现了则将当前容器中的beanFactory,environment放入异常分析器中。因为万一在BeanFactory,Environment织入之前springboot启动报错的话,异常分析器会得不到容器的beanFactory,environment对象。
private List<FailureAnalyzer> handleAwareAnalyzers(List<FailureAnalyzer> analyzers,
ConfigurableApplicationContext context) {
List<FailureAnalyzer> awareAnalyzers = analyzers.stream()
.filter((analyzer) -> analyzer instanceof BeanFactoryAware || analyzer instanceof EnvironmentAware)
.collect(Collectors.toList());
if (!awareAnalyzers.isEmpty()) {
String awareAnalyzerNames = StringUtils.collectionToCommaDelimitedString(awareAnalyzers.stream()
.map((analyzer) -> analyzer.getClass().getName())
.collect(Collectors.toList()));
logger.warn(LogMessage.format(
"FailureAnalyzers [%s] implement BeanFactoryAware or EnvironmentAware. "
+ "Support for these interfaces on FailureAnalyzers is deprecated, "
+ "and will be removed in a future release. "
+ "Instead provide a constructor that accepts BeanFactory or Environment parameters.",
awareAnalyzerNames));
if (context == null) {
logger.trace(LogMessage.format("Skipping [%s] due to missing context", awareAnalyzerNames));
return analyzers.stream()
.filter((analyzer) -> !awareAnalyzers.contains(analyzer))
.collect(Collectors.toList());
}
awareAnalyzers.forEach((analyzer) -> {
if (analyzer instanceof BeanFactoryAware) {
((BeanFactoryAware) analyzer).setBeanFactory(context.getBeanFactory());
}
if (analyzer instanceof EnvironmentAware) {
((EnvironmentAware) analyzer).setEnvironment(context.getEnvironment());
}
});
}
return analyzers;
}
最后根据捕获到的springboot启动的异常得到对应的异常分析器。再从缓存中取出FailureAnalysisReporter进行异常汇报
@Override
public boolean reportException(Throwable failure) {
FailureAnalysis analysis = analyze(failure, this.analyzers);
return report(analysis, this.classLoader);
}
private boolean report(FailureAnalysis analysis, ClassLoader classLoader) {
List<FailureAnalysisReporter> reporters = SpringFactoriesLoader.loadFactories(FailureAnalysisReporter.class,
classLoader);
if (analysis == null || reporters.isEmpty()) {
return false;
}
for (FailureAnalysisReporter reporter : reporters) {
reporter.report(analysis);
}
return true;
}
environment 系统环境
在springboot启动流程中,调用以下方法初始化environment。将不同的环境信息封装到不同的propertySources中。并按顺序排序,如果不同的propertySource中有相同的配置,则按照排序顺序取值。
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// 初始化environment对象,同时在父类的构造函数中读取操作系统变量(env)以及应用环境变量(propertis)
// 如果是servlet应用还会读取servletConfigInitParams变量以及servletContextInitParams变量
ConfigurableEnvironment environment = getOrCreateEnvironment();
//读取启动参数到environment中
configureEnvironment(environment, applicationArguments.getSourceArgs());
//读取configurationProperty配置,并放到第一位。
ConfigurationPropertySources.attach(environment);
//使用SpringApplicationRunListener监听器发布environment事件。
//EnvironmentPostProcessorApplicationListener监听environment事件
//拿到EnvironmentPostProcessor所有的实现类。并执行增强方法。
//该步骤主要能得到bootStrap.yml文件和application.yml文件的配置信息
//后续不同环境的application.yml文件以及apollo配置信息在BeanFactoryPostProcessor对容器进行增强时读取
listeners.environmentPrepared(bootstrapContext, environment);
DefaultPropertiesPropertySource.moveToEnd(environment);
Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
"Environment prefix cannot be set via properties.");
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());
environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
SpringApplicationRunListener 运行时监听器
通过spi机制读取springfactories文件中获取SpringApplicationRunListener的实现类,并存入SpringApplicationRunListeners中。当springboot启动时即可通过SpringApplicationRunListeners中调用所有监听器处理事件。springboot中自带了一个监听器EventPublishingRunListener,将对应事件广播给springboot的监听器处理。environment准备时也是通过该种方式实现。SpringApplicationRunListener中主要有以下几个事件。
//springboot开始启动
default void starting(ConfigurableBootstrapContext bootstrapContext) {
}
//准备environment
default void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,
ConfigurableEnvironment environment) {
}
//准备context
default void contextPrepared(ConfigurableApplicationContext context) {
}
//加载context
default void contextLoaded(ConfigurableApplicationContext context) {
}
//context刷新并启动完成
default void started(ConfigurableApplicationContext context, Duration timeTaken) {
started(context);
}
//CommandLineRunner和ApplicationRunner已经执行
default void ready(ConfigurableApplicationContext context, Duration timeTaken) {
running(context);
}
//springboot启动失败
default void failed(ConfigurableApplicationContext context, Throwable exception) {
}
创建、初始化、刷新 ApplicationContex容器
待续