SpringBoot2启动流程分析
首先上一张图,图片来自 SpringBoot启动流程解析

本文基于spring-boot-2.0.4.RELEASE.jar包分析。
程序启动入口
public static void main(String[] args) {
SpringApplication.run(Springboot2Application.class, args);
}
run是一个静态方法,最后会调用创建SpringApplication实例并run
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class[]{primarySource}, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
我们先看new SpringApplication(xx)构建的实例。
public SpringApplication(Class... primarySources) {
this((ResourceLoader)null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
this.sources = new LinkedHashSet();
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = new HashSet();
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
//配置source
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
//判断是否web应用
this.webApplicationType = this.deduceWebApplicationType();
//创建初始化构造器
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
//创建应用监听器
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
//推断出main方法类
this.mainApplicationClass = this.deduceMainApplicationClass();
}
SpringApplication的构造函数主要设置了一些基本参数并配置source、判断了是否web应用、创建初始化构造器、创建应用监听器、找出main方法所在的类。
getSpringFactoriesInstances为获取spring工厂中的实例,具体代码块为
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return this.getSpringFactoriesInstances(type, new Class[0]);
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
//获取类加载器
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
//通过类加载器、获取指定的spring.factories文件,并获取文件中工厂类的全路径名
Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//通过类路径反射得到工厂class对象、构造方法
List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
new SpringApplication(xx)构建完实例后,会进行run方法。
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
//应用启动计时器开始计时
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
//Headless模式配置
configureHeadlessProperty();
//获取启动监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
//应用启动监听器开始计时
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//配置环境模块(祥见下面prepareEnvironment方法)
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
//配置需要忽略的bean
configureIgnoreBeanInfo(environment);
//Banner配置
Banner printedBanner = printBanner(environment);
//创建应用上下文对象
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//上下文基本属性配置(祥见下面prepareContext方法)
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//更新应用上下文(祥见下面refresh方法)
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// 创建配置环境
ConfigurableEnvironment environment = getOrCreateEnvironment();
//加载属性文件
configureEnvironment(environment, applicationArguments.getSourceArgs());
//监听器监听配置
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (this.webApplicationType == WebApplicationType.NONE) {
environment = new EnvironmentConverter(getClassLoader())
.convertToStandardEnvironmentIfNecessary(environment);
}
ConfigurationPropertySources.attach(environment);
return environment;
}
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//加载配置环境
context.setEnvironment(environment);
//ResourceLoader资源加载器
postProcessApplicationContext(context);
//初始化环境
applyInitializers(context);
//配置监听
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
context.getBeanFactory().registerSingleton("springApplicationArguments",
applicationArguments);
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
//加载启动参数
load(context, sources.toArray(new Object[0]));
//监听加载应用上下文
listeners.contextLoaded(context);
}
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
//准备更新上下文时的预备工作:1.初始化PropertySource; 2.验证Enrivonment中必要的属性
this.prepareRefresh();
//获取上下文中的BeanFactory
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//对BeanFactory做些预备工作
this.prepareBeanFactory(beanFactory);
try {
//对BeanFactory进行预处理
this.postProcessBeanFactory(beanFactory);
//执行容器中的BeanFactoryPostProcessor
this.invokeBeanFactoryPostProcessors(beanFactory);
//注册BeanPostProcessor
this.registerBeanPostProcessors(beanFactory);
//初始化MessageSource(国际化相关)
this.initMessageSource();
//初始化容器事件广播器(用来发布事件)
this.initApplicationEventMulticaster();
//初始化一些特殊的Bean,主要做了: 1.初始化ThemeSource(跟国际化相关的接口) 2.创建WebServer
this.onRefresh();
//将所有监听器注册到前两步创建的事件广播器中
this.registerListeners();
//结束BeanFactory的初始化工作(这一步主要用来将所有的单例BeanDefinition实例化)
this.finishBeanFactoryInitialization(beanFactory);
//上下文刷新完毕
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
SpringBoot2启动流程分析的更多相关文章
- SpringBoot启动流程分析(五):SpringBoot自动装配原理实现
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(六):IoC容器依赖注入
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(一):SpringApplication类初始化过程
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(二):SpringApplication的run方法
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(三):SpringApplication的run方法之prepareContext()方法
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(四):IoC容器的初始化过程
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- u-boot启动流程分析(2)_板级(board)部分
转自:http://www.wowotech.net/u-boot/boot_flow_2.html 目录: 1. 前言 2. Generic Board 3. _main 4. global dat ...
- u-boot启动流程分析(1)_平台相关部分
转自:http://www.wowotech.net/u-boot/boot_flow_1.html 1. 前言 本文将结合u-boot的“board—>machine—>arch—> ...
- Cocos2d-x3.3RC0的Android编译Activity启动流程分析
本文将从引擎源代码Jni分析Cocos2d-x3.3RC0的Android Activity的启动流程,以下是具体分析. 1.引擎源代码Jni.部分Java层和C++层代码分析 watermark/2 ...
随机推荐
- Servlet身份验证过滤器
文件:index.html 文件:MyFilter.java 文件:MyServlet.java 文件:web.xml
- @codeforces - 932F@ Escape Through Leaf
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个 n 个点的树(标号1~n),以结点 1 为根.每个结点 ...
- ArcGIS 发布高程服务。10.4
ArcGIS 发布高程必须是10.21以上,我用10.4. 前端用ArcGIS For API 4.x. ARCGIS很早之前有CS版本的ArcScene,可查看高程TIF文件,但机制和BS的完全不同 ...
- Oracle使用——PLSQL查询表结构并导出EXCEL
背景 有一次需要查询Oracle数据库中的所有表接口并且导出excel,方法记录如下 使用 使用PLSQL工具查询表结构,SQL语句如下 SELECT B.TABLE_NAME AS '表名', C. ...
- Python操作pymysql写入数据库时的错误
错误一 InternalError: (pymysql.err.InternalError) (1366, "Incorrect string value: '\\xE6\\xAD\\xA3 ...
- 洛谷 2149 [SDOI2009]Elaxia的路线
题目描述 最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间.Elaxia和w每天都要奔波于宿舍和实验室之间,他们 希望在节约时间的 ...
- LeetCode70 Climbing Stairs
题目: You are climbing a stair case. It takes n steps to reach to the top. Each time you can either cl ...
- 删除username的索引
-- 删除index_name 索引 drop index index_name on user; show index from user \G; -- 创建新索引列组成,index_pinyin为 ...
- windows环境下安装nodeJS和express,一直提示command not found-配置环境变量
1.安装NodeJS后,使用npm指令安装express框架,使用 npm install -g express npm install -g express-generator 安装了大半天的时间, ...
- jquery tab点击切换的问题
问题: 页面结构见下 <div id="wrap"> <li> <a href="#" class="active&qu ...