首先上一张图,图片来自 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启动流程分析的更多相关文章

  1. SpringBoot启动流程分析(五):SpringBoot自动装配原理实现

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  2. SpringBoot启动流程分析(六):IoC容器依赖注入

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  3. SpringBoot启动流程分析(一):SpringApplication类初始化过程

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  4. SpringBoot启动流程分析(二):SpringApplication的run方法

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  5. SpringBoot启动流程分析(三):SpringApplication的run方法之prepareContext()方法

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  6. SpringBoot启动流程分析(四):IoC容器的初始化过程

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  7. u-boot启动流程分析(2)_板级(board)部分

    转自:http://www.wowotech.net/u-boot/boot_flow_2.html 目录: 1. 前言 2. Generic Board 3. _main 4. global dat ...

  8. u-boot启动流程分析(1)_平台相关部分

    转自:http://www.wowotech.net/u-boot/boot_flow_1.html 1. 前言 本文将结合u-boot的“board—>machine—>arch—> ...

  9. Cocos2d-x3.3RC0的Android编译Activity启动流程分析

    本文将从引擎源代码Jni分析Cocos2d-x3.3RC0的Android Activity的启动流程,以下是具体分析. 1.引擎源代码Jni.部分Java层和C++层代码分析 watermark/2 ...

随机推荐

  1. iOS7之后JavaScript与Objective-C之间的通信

    http://www.cocoachina.com/ios/20150906/13320.html 最近公司用Ping++集成了第三方支付,并且微信端也集成了这个功能,而微信付款时需要调用原生的支付宝 ...

  2. GCD使用经验与技巧浅谈

    前言 GCD(Grand Central Dispatch)可以说是Mac.iOS开发中的一大“利器”,本文就总结一些有关使用GCD的经验与技巧. dispatch_once_t必须是全局或stati ...

  3. Java练习 SDUT-2400_高中数学?

    高中数学? Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 高中数学大家都学过数列,其中一个重要的概念就是数列的通项,可 ...

  4. 从Kubernetes 1.14 发布,看技术社区演进方向

    Kubernetes 1.14 正式发布已经过去了一段时间,相信你已经从不同渠道看过了各种版本的解读. 不过,相比于代码 Release,马上就要迎来5周岁生日的Kubernetes 项目接下来如何演 ...

  5. 罗列Python标准模块

    文本 1. string:通用字符串操作 2. re:正则表达式操作 3. difflib:差异计算工具 4. textwrap:文本填充 5. unicodedata:Unicode字符数据库 6. ...

  6. python内置函数and匿名函数

    一.内置函数 什什么是内置函数? 就是python给你提供的. 拿来直接⽤用的函数, 比如print., input等等. 截⽌止 到python版本3.6.2 python⼀一共提供了了68个内置函 ...

  7. SharpDX初学者教程第5部分:着色三角形

    原文 http://www.johanfalk.eu/blog/sharpdx-beginners-tutorial-part-5-coloring-the-triangle 在第4部分中,我们创建了 ...

  8. SDUT-2118_数据结构实验之链表三:链表的逆置

    数据结构实验之链表三:链表的逆置 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 输入多个整数,以-1作为结束标志,顺序 ...

  9. Flask学习之二 模板

    继续学习flask 本部分Miguel Grinberg教程的翻译地址:http://www.pythondoc.com/flask-mega-tutorial/templates.html 英文原文 ...

  10. ip2long与long2IP 分析

    <?php $ip='47.93.97.127'; $long=sprintf("%u",ip2long($ip));//string(9) "794648959& ...