springboot启动类
package com.ahs.ahsaccount;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AhsAccountApplication {
public static void main(String[] args) {
SpringApplication.run(AhsAccountApplication.class, args);
}
}
run方法
//SpringApplication.class
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
将启动类放入primarySources
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//根据classpath 下的类,推算当前web应用类型(REACTIVE, servlet)
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//去spring.factories 中去获取所有key:org.springframework.context.ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//去spring.factories 中去获取所有key: org.springframework.context.ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//根据main方法推算出mainApplicationClass
this.mainApplicationClass = deduceMainApplicationClass();
}
获取启动类
获取web应用类型
读取了ApplicationContextInitializer ,ApplicationListener
根据main推算出所在的类
// SpringApplication.java
public ConfigurableApplicationContext run(String... args) {
// 创建 StopWatch 对象,并启动。StopWatch 主要用于简单统计 run 启动过程的时长。
StopWatch stopWatch = new StopWatch();
//是记录了启动开始时间
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 配置 headless 属性
configureHeadlessProperty();
// 去spring.factroies中读取了SpringApplicationRunListener 的组件, 就是用来发布事件或者运行监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
//发布1.ApplicationStartingEvent事件,在运行开始时发送
listeners.starting();
try {
// 创建 ApplicationArguments 对象
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 加载属性配置。执行完成后,所有的 environment 的属性都会加载进来,包括 application.properties 和外部的属性配置。预初始化环境: 读取环境变量,读取配置文件信息(基于监听器)
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 忽略beaninfo的bean
configureIgnoreBeanInfo(environment);
// 打印Banner 横幅
Banner printedBanner = printBanner(environment);
// 创建 Spring 容器。 根据webApplicationType创建Spring上下文
context = createApplicationContext();
// 异常报告器
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 主要是调用所有初始化类的 initialize 方法,/预初始化spring上下文
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
// 初始化 Spring 容器。ioc流程
refreshContext(context);
// 执行 Spring 容器的初始化的后置逻辑。默认实现为空。
afterRefresh(context, applicationArguments);
// 停止 StopWatch 统计时长
stopWatch.stop();
// 打印 Spring Boot 启动的时长日志。
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
// 通知 SpringApplicationRunListener 的数组,Spring 容器启动完成。
listeners.started(context);
// 调用 ApplicationRunner 或者 CommandLineRunner 的运行方法。
callRunners(context, applicationArguments);
} catch (Throwable ex) {
// 如果发生异常,则进行处理,并抛出 IllegalStateException 异常
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
// 通知 SpringApplicationRunListener 的数组,Spring 容器运行中。
try {
listeners.running(context);
} catch (Throwable ex) {
// 如果发生异常,则进行处理,并抛出 IllegalStateException 异常
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
// SpringApplication.java
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
// Create and configure the environment
// 创建 ConfigurableEnvironment 对象,并进行配置
//根据webApplicationType 创建Environment 创建就会读取: java环境变量和系统环境变量
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
// 通知 SpringApplicationRunListener 的数组,环境变量已经准备完成。
//发布了ApplicationEnvironmentPreparedEvent 的监听器 读取了全局配置文件
listeners.environmentPrepared(environment);
// 绑定 environment 到 SpringApplication 上
bindToSpringApplication(environment);
// 如果非自定义 environment ,则根据条件转换
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
}
// 如果有 attach 到 environment 上的 MutablePropertySources ,则添加到 environment 的 PropertySource 中。
ConfigurationPropertySources.attach(environment);
return environment;
}
// SpringApplication.java
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
// <1> 设置 context 的 environment 属性
context.setEnvironment(environment);
// <2> 设置 context 的一些属性
postProcessApplicationContext(context);
// <3> 初始化 ApplicationContextInitializer
//拿到之前读取到所有ApplicationContextInitializer的组件, 循环调用initialize方法
applyInitializers(context);
// <4> 通知 SpringApplicationRunListener 的数组,Spring 容器准备完成。
listeners.contextPrepared(context);
// <5> 打印日志
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
// <6> 设置 beanFactory 的属性
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
// Load the sources
// <7> 加载 BeanDefinition 们
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
// <8> 通知 SpringApplicationRunListener 的数组,Spring 容器加载完成。
listeners.contextLoaded(context);
}
// SpringApplication.java
private void refreshContext(ConfigurableApplicationContext context) {
// <1> 开启(刷新)Spring 容器
refresh(context);
// <2> 注册 ShutdownHook 钩子
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
} catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
}
扩展点
// SpringApplication.java
private void callRunners(ApplicationContext context, ApplicationArguments args) {
// <1> 获得所有 Runner 们
List<Object> runners = new ArrayList<>();
// <1.1> 获得所有 ApplicationRunner Bean 们
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
// <1.2> 获得所有 CommandLineRunner Bean 们
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
// <1.3> 排序 runners
AnnotationAwareOrderComparator.sort(runners);
// <2> 遍历 Runner 数组,执行逻辑
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}
1、初始化SpringApplication 从spring.factories 读取 listener ApplicationContextInitializer 。
2.运行run方法
3.读取 环境变量 配置信息等
4. 创建springApplication上下文:ServletWebServerApplicationContext
5. . 预初始化上下文
6.调用refresh 加载ioc容器 加载所有的自动配置类
7、创建servlet容器
8.整个流程中会多次调用很多监听器对外进行