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 声明

指定 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 事件方法

SpringBoot是如何动起来的的更多相关文章

  1. 尚硅谷springboot学习35-启动原理

    先列出几个重要的事件回调机制 配置在META-INF/spring.factories ApplicationContextInitializer SpringApplicationRunListen ...

  2. 尚硅谷springboot学习14-自动配置原理

    配置文件能配置哪些属性 配置文件能配置的属性参照 自动配置的原理 1).SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration 2).@Ena ...

  3. SpringBoot是如何动起来的?

    程序入口 SpringApplication.run(BeautyApplication.class, args); 执行此方法来加载整个SpringBoot的环境. 1. 从哪儿开始? Spring ...

  4. 厉害了!SpringBoot是如何动起来的!

    程序入口 SpringApplication.run(BeautyApplication.class, args); 执行此方法来加载整个SpringBoot的环境. 1. 从哪儿开始? Spring ...

  5. 2.SpringBoot HelloWorld详解

    1.POM文件 父项目 <parent> <groupId>org.springframework.boot</groupId> <artifactId> ...

  6. springboot Hello World探究

    Hello World探究1.POM文件1.父项目 <parent>     <groupId>org.springframework.boot</groupId> ...

  7. SpringBoot入门(简单详细教程)

    Spring Boot 简介 简化Spring应用开发的一个框架:整个Spring技术栈的一个大整合:J2EE开发的一站式解决方案: 微服务 martin fowler:微服务:架构风格(服务微化): ...

  8. springboot核心技术(一)-----入门、配置

    Hello World 1.创建一个maven工程:(jar) 2.导入spring boot相关的依赖 <parent> <groupId>org.springframewo ...

  9. 1、spring boot入门

    1.Spring Boot 简介 简化Spring应用开发的一个框架: 整个Spring技术栈的一个大整合: J2EE开发的一站式解决方案: 2.微服务 2014,martin fowler 微服务: ...

随机推荐

  1. 微信小程序1

    本次项目主要了解及使用微信小程序,以及更好的理解微信动画,wxss,JavaScript,ajax,xml等技术: 借助的平台是java后端设计语言以及微信小程序界面,设计 该系统分为1,个人用户端: ...

  2. Python入门经典. 以解决计算问题为导向的Python编程实践

    Python入门经典. 以解决计算问题为导向的Python编程实践(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1juLsew8UiOErRheQPOuTaw 提取 ...

  3. 几个VB常见又内涵的错误

    第一位内涵的就是:没有对象 找到对象,却发现是别人的对象 不能加载也不能卸载...这到底是什么对象 哈哈哈~

  4. Tomcat手动部署Web项目详细步骤

    阅读须知:文章基于Tomcat8,其它版本若有差异,请自行辨别.本文为博主原创文章,转载请附原文链接. 不借助任何IDE,这里介绍在Tomcat中手动部署web项目的三种方式: 1.部署解包的weba ...

  5. 转 Singleton clr via c#3

    /// <summary> /// 注意 只有在构造器没有副作用的时候才能使用这个技术 /// </summary> class Singleton { private sta ...

  6. zstd --压缩工具

    Zstandard (也被称为zstd )是一款免费的开源,快速实时数据压缩程序,具有更好的压缩比 (约为 10:1). 安装 yum group install "Development ...

  7. 详解封装微信小程序组件及小程序坑(附带解决方案)

    一.序 上一篇介绍了如何从零开发微信小程序,博客园审核变智障了,每次代码都不算篇幅,好好滴一篇原创,不到3分钟从首页移出来了.这篇介绍一下组件封装和我的踩坑历程. 二.封装微信小程序可复用组件 首先模 ...

  8. 什么是URL,URL格式

    什么是URL: 互联网里有很多的网页,大家都需要能够互相访问,就比如在一栋大楼里,有很多的房间,不同房间里的人都想能去任意的其他房间里去,那怎么能够达到这样的想法呢? 很简单,每个房间都挂一个门牌号就 ...

  9. 关于Tensorflow安装opencv和pygame

    1.安装opencv https://www.lfd.uci.edu/~gohlke/pythonlibs/#opencv C:\ProgramData\Anaconda3\Lib\site-pack ...

  10. SQL Server Cast、Convert数据类型转换

    一.概述 本篇文章转载来着官网在线文档,文章主要介绍SQL Server数据类型转换相关语法.隐式转换.Date样式等. 语法 Syntax for CAST: CAST ( expression A ...