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 ...
随机推荐
- 解决:"UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position"错误
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/Haiyang_Duan/article/ ...
- oracle回滚机制深入研究
这篇文章主要描写叙述oracle的回滚机制,篇幅可能较长,由于对于oracle的回滚机制来说,要讨论和描写叙述的实在太多,仅仅能刷选自己觉得最有意义的一部分进行深入研究和分享 一.我们来看一个DML语 ...
- maven 从svn导入项目遇到的问题 No marketplace entries found to handle yuicompressor maven plugin:1.3.0:compile
版权声明:本文为博主原创文章,未经博主同意不得转载.安金龙 的博客. https://blog.csdn.net/smile0198/article/details/25463825 RT.使用ecl ...
- 洛谷 3174 [HAOI2009]毛毛虫
题目描述 对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大.例如下图左边的树(图 1 )抽出一部分就变成了右边的一个毛毛虫了(图 2 ). 输入输出格 ...
- cPickle对python对象进行序列化,序列化到文件或内存
pickle模块使用的数据格式是python专用的,并且不同版本不向后兼容,同时也不能被其他语言说识别.要和其他语言交互,可以使用内置的json包 cPickle可以对任意一种类型的python对象进 ...
- 08查找满足条件的n个数
第一节.寻找和为定值的两个数 题目:输入一个数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字.要求时间复杂度是O(n).如果有多对数字的和等于输入的数字,输出任意一对即可. 例如输 ...
- 模板—堆优化dijkstra
];]; void dijkstra(int s) { memset(dis,0x7f,sizeof(dis));ma(v); priority_queue<pair<int,int> ...
- 初识block
我们可以把Block当做Objective-C的匿名函数.Block允许开发者在两个对象之间将任意的语句当做数据进行传递,往往这要比引用定义在别处的函数直观.另外,block的实现具有封闭性(clos ...
- PAN-OS 6.1 Open Source Software (OSS) Listing
https://www.paloaltonetworks.com/documentation/oss-listings/oss-listings/pan-os-oss-listings/pan-os- ...
- sleep usleep nanosleep alarm setitimer使用
sleep使用的是alarm之类的定时器,定时器是使得进程被挂起,使进程处于就绪的状态. signal+alarm定时器 alarm参数的类型为uint, 并且不能填0 #include <st ...