SpringBoot是如何动起来的?
程序入口
SpringApplication.run(BeautyApplication.class, args);
执行此方法来加载整个SpringBoot的环境。
1. 从哪儿开始?
SpringApplication.java
/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
//...
}
调用SpringApplication.java 中的 run 方法,目的是加载Spring Application,同时返回 ApplicationContext。
2. 执行了什么?
2.1 计时
记录整个Spring Application的加载时间!
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// ...
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
2.2 声明
// 声明 ApplicationContext
ConfigurableApplicationContext context = null;
// 声明 一个异常报告集合
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
2.3 指定程序运行模式
指定 java.awt.headless,默认是true 一般是在程序开始激活headless模式,告诉程序,现在你要工作在Headless mode下,就不要指望硬件帮忙了,你得自力更生,依靠系统的计算能力模拟出这些特性来。
private void configureHeadlessProperty() {
System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, System.getProperty(
SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}
2.4 配置监听并发布应用启动事件
SpringApplicationRunListener 负责加载 ApplicationListener事件。
SpringApplicationRunListeners listeners = getRunListeners(args);
// 开始
listeners.starting();
// 处理所有 property sources 配置和 profiles 配置,准备环境,分为标准 Servlet 环境和标准环境
ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
// 准备应用上下文
prepareContext(context, environment, listeners, applicationArguments,printedBanner);
// 完成
listeners.started(context);
// 异常
handleRunFailure(context, ex, exceptionReporters, listeners);
// 执行
listeners.running(context);
getRunListeners 中根据 type = SpringApplicationRunListener.class 去拿到了所有的 Listener 并根据优先级排序。
对应的就是 META-INF/spring.factories 文件中的
org.springframework.boot.SpringApplicationRunListener=org.springframework.boot.context.event.EventPublishingRunListener private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
在 ApplicationListener 中 , 可以针对任何一个阶段插入处理代码。
public interface SpringApplicationRunListener {
/**
* Called immediately when the run method has first started. Can be used for very
* early initialization.
*/
void starting();
/**
* Called once the environment has been prepared, but before the
* {@link ApplicationContext} has been created.
* @param environment the environment
*/
void environmentPrepared(ConfigurableEnvironment environment);
/**
* Called once the {@link ApplicationContext} has been created and prepared, but
* before sources have been loaded.
* @param context the application context
*/
void contextPrepared(ConfigurableApplicationContext context);
/**
* Called once the application context has been loaded but before it has been
* refreshed.
* @param context the application context
*/
void contextLoaded(ConfigurableApplicationContext context);
/**
* The context has been refreshed and the application has started but
* {@link CommandLineRunner CommandLineRunners} and {@link ApplicationRunner
* ApplicationRunners} have not been called.
* @param context the application context.
* @since 2.0.0
*/
void started(ConfigurableApplicationContext context);
/**
* Called immediately before the run method finishes, when the application context has
* been refreshed and all {@link CommandLineRunner CommandLineRunners} and
* {@link ApplicationRunner ApplicationRunners} have been called.
* @param context the application context.
* @since 2.0.0
*/
void running(ConfigurableApplicationContext context);
/**
* Called when a failure occurs when running the application.
* @param context the application context or {@code null} if a failure occurred before
* the context was created
* @param exception the failure
* @since 2.0.0
*/
void failed(ConfigurableApplicationContext context, Throwable exception);
}
3. 每个阶段执行的内容
3.1 listeners.starting();
在加载Spring Application之前执行,所有资源和环境未被加载。
3.2 prepareEnvironment(listeners, applicationArguments);
创建 ConfigurableEnvironment;将配置的环境绑定到Spring Application中;
private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
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;
}
3.3 prepareContext
配置忽略的Bean;
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
if (System.getProperty(
CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
Boolean ignore = environment.getProperty("spring.beaninfo.ignore",
Boolean.class, Boolean.TRUE);
System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME,
ignore.toString());
}
}
打印日志-加载的资源
Banner printedBanner = printBanner(environment);
根据不同的WebApplicationType创建Context
context = createApplicationContext();
3.4 refreshContext
支持定制刷新
/**
* Register a shutdown hook with the JVM runtime, closing this context
* on JVM shutdown unless it has already been closed at that time.
* <p>This method can be called multiple times. Only one shutdown hook
* (at max) will be registered for each context instance.
* @see java.lang.Runtime#addShutdownHook
* @see #close()
*/
void registerShutdownHook();
3.5 afterRefresh
刷新后的实现方法暂未实现
/**
* Called after the context has been refreshed.
* @param context the application context
* @param args the application arguments
*/
protected void afterRefresh(ConfigurableApplicationContext context,
ApplicationArguments args) {
}
3.6 listeners.started(context);
到此为止, Spring Application的环境和资源都加载完毕了;发布应用上下文启动完成事件;执行所有 Runner 运行器 - 执行所有 ApplicationRunner 和 CommandLineRunner 这两种运行器。
// 启动
callRunners(context, applicationArguments);
3.7 listeners.running(context);
触发所有 SpringApplicationRunListener 监听器的 running 事件方法。
微信讨论群,如果微信失效请加 shengruxiahua3596 拉你入群

SpringBoot是如何动起来的?的更多相关文章
- SpringBoot是如何动起来的
SpringBoot是如何动起来的 程序入口 SpringApplication.run(BeautyApplication.class, args); 执行此方法来加载整个SpringBoot的环境 ...
- 尚硅谷springboot学习35-启动原理
先列出几个重要的事件回调机制 配置在META-INF/spring.factories ApplicationContextInitializer SpringApplicationRunListen ...
- 尚硅谷springboot学习14-自动配置原理
配置文件能配置哪些属性 配置文件能配置的属性参照 自动配置的原理 1).SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration 2).@Ena ...
- 厉害了!SpringBoot是如何动起来的!
程序入口 SpringApplication.run(BeautyApplication.class, args); 执行此方法来加载整个SpringBoot的环境. 1. 从哪儿开始? Spring ...
- 2.SpringBoot HelloWorld详解
1.POM文件 父项目 <parent> <groupId>org.springframework.boot</groupId> <artifactId> ...
- springboot Hello World探究
Hello World探究1.POM文件1.父项目 <parent> <groupId>org.springframework.boot</groupId> ...
- SpringBoot入门(简单详细教程)
Spring Boot 简介 简化Spring应用开发的一个框架:整个Spring技术栈的一个大整合:J2EE开发的一站式解决方案: 微服务 martin fowler:微服务:架构风格(服务微化): ...
- springboot核心技术(一)-----入门、配置
Hello World 1.创建一个maven工程:(jar) 2.导入spring boot相关的依赖 <parent> <groupId>org.springframewo ...
- 1、spring boot入门
1.Spring Boot 简介 简化Spring应用开发的一个框架: 整个Spring技术栈的一个大整合: J2EE开发的一站式解决方案: 2.微服务 2014,martin fowler 微服务: ...
随机推荐
- 03: OpenGL ES 基础教程02 使用OpenGL ES 基本步骤
第二章:让硬件为你工作(OpenGL ES 应用实践指南 iOS卷) 前言: 1:使用OpenGL ES 基本步骤 2:绘制三角形 3:效果 正文: 一:使用OpenGL ES 基本步骤 1:生成缓存 ...
- (3)安装elastic6.1.3及插件kibana,x-pack,essql,head,bigdesk,cerebro,ik
6安装nginx 6.1安装nginx 安装 pcre,zlib,openssl,nginx 6.2生成web访问用户密码 htpasswd –c –b /usr/local/nginx/conf/p ...
- angularjs1学习笔记--持续更新
angularJS使用的MVC为何不属于二十三种设计模式之一? MVC被GoF (Gang of Four,四人组, <Design Patterns: Elements of Reusable ...
- 基于Spark的电影推荐系统(电影网站)
第一部分-电影网站: 软件架构: SpringBoot+Mybatis+JSP 项目描述:主要实现电影网站的展现 和 用户的所有动作的地方 技术选型: 技术 名称 官网 Spring Boot 容器 ...
- 深度汉化GCompris-qt,免费的幼儿识字软件
1 需求 因为有个小孩上幼儿园了,想开始教他一些汉语拼音和基本的汉字,但通过一书本和卡片又有些枯燥乏味,于上就上网搜索一些辅助认字的应用,还购买了悟空识字APP,在用的过程中发现他设置了很严格的关卡, ...
- JS中数据类型转换
JS中数据类型转换汇总 JS中的数据类型分为 [基本数据类型] 数字 number 字符串 string 布尔 boolean 空 null 未定义 undefined [引用数据类型] 对象 obj ...
- opencv边缘检测-拉普拉斯算子
sobel算子一文说了,索贝尔算子是模拟一阶求导,导数越大的地方说明变换越剧烈,越有可能是边缘. 那如果继续对f'(t)求导呢? 可以发现"边缘处"的二阶导数=0. 我们可以利用这 ...
- Idea 配置Jrebel热部署
虽说Idea自带热更新功能,但是一旦mapper更改,则不能及时更新,影响开发效率. 接下来,我们来配置Jrebel热更新,简单方便实用. 第一步:进入插件下载页面. 第二步:安装jrebel插件. ...
- markdown常用语法使用笔记
markdown是当下比较流行的一种编辑标记语言,很多系统都支持markdown语法来编辑文件内容,像gitbook之类的,一下是一些学习笔记. 1.开头用#的数量表示1-6阶的标题,结尾可以以任意数 ...
- Angular2+之使用FormGroup、FormBuilder和Validators对象控制表单(取值、赋值、校验和是否可编辑等)
1.要使用Angular自带的表单控制需要先引入相关模块(.ts文件): import { FormGroup, //表单对象类 FormBuilder, //表单生成工具类 Validators} ...