SpringBoot之SpringApplication Explain
SpringApplication Explain
The
SpringApplicationclass provides a convenient way to bootstrap a Spring application that is started from amain()method. In many situations, you can delegate to the staticSpringApplication.runmethod, as shown in the following example.(SpringApplication类提供了一种便利的方式以便引导Spring应用从
#main启动,大多数情况下,可以通过静态方法SpringApplication#run代理启动)
How TO Use SpringApplication
@EnableAutoConfiguration
public class MyApplication {
// ... Bean definitions
public static void main(String[] args) throws Exception {
SpringApplication.run(MyApplication.class, args);
}
}
Customize SpringApplication
UseSpringApplicationAPI To Change
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MySpringConfiguration.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}
UseSpringApplicationBuilder API To Change
new SpringApplicationBuilder()
.sources(Parent.class)
.child(Application.class)
.bannerMode(Banner.Mode.OFF)
.run(args);
SpringApplication Preparing Stage
Configure Spring Boot Bean's Sources
Java 配置类或XML上下文配置集合,用于Spring Boot BeanDefinitionLoader读取,并且将配置源解析加载为Spring Bean 定义。
- 数量,一个或者多个
Java Configuration Class
使用Spring 注解驱动中的Java配置类,也就是Spring 模式注解所标注的类,例如@Configuration
package com.yi23.backend.springboot.bootstrap;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* {@link SpringApplication} 启动引导类
*
* @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang</a>
* @see
* @since
*/
@SpringBootApplication
public class SpringApplicationBootstrap {
public static void main(String[] args) {
SpringApplication.run(SpringApplicationBootstrap.class,args);
}
}
XML Configure
用户Spring 传统配置驱动的XML文件
...
//设置Annotation配置源
Set<String> sources = new HashSet<>();
//A source can be: a class name, package name, or an XML resource location.
sources.add(Yi23ApplicationConfiguration.class.getName());
springApplication.setSources(sources);
...
Deduce Web Application Type
根据当前应用CLassPath中是否存在相关实现来推断Web Application Type,包括:
- Web Reactive :
WebApplicationType.REACTIVE - Web Servlet :
WebApplicationType.SERVLET - 非Web :
WebApplicationType.NONE
参考:org.springframework.boot.SpringApplication#deduceWebApplicationType
private WebApplicationType deduceWebApplicationType() {
if (ClassUtils.isPresent(REACTIVE_WEB_ENVIRONMENT_CLASS, null)
&& !ClassUtils.isPresent(MVC_WEB_ENVIRONMENT_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : WEB_ENVIRONMENT_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
- 版本意识,下图为Spring Boot 2.1.3中的推断实现

Deduce Main Class
跟住main线程的执行堆栈判断当前实际的引导类
参考:org.springframework.boot.SpringApplication#deduceMainApplicationClass
private Class<?> deduceMainApplicationClass() {
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
}
catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}
Load ApplicationContextInitializer
ApplicationContextInitializer是应用上下文的加载器,利用Spring 工厂加载机制,实例化ApplicationContextInitializer实现类,并实现对象集合排序
- 代码
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;
}
- 实现技术
- 实现类:
org.springframework.core.io.support.SpringFactoriesLoader - 配置文件:
META-INF/spring.factories - 排序:
org.springframework.core.annotation.AnnotationAwareOrderComparator#sort
- 实现类:
package com.yi23.backend.springboot.context;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
/**
* 自定义高优先级{@link ApplicationContextInitializer}初始化加载器
*
* @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang</a>
* @see
* @since
*/
@Order(Ordered.HIGHEST_PRECEDENCE)
public class HelloYi23ApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("高优先级初始化加载class : "
+ applicationContext.getId());
}
}
# Initializers
org.springframework.context.ApplicationContextInitializer=\
com.yi23.backend.springboot.context.AfterHelloYi23ApplicationContextInitializer,\
com.yi23.backend.springboot.context.HelloYi23ApplicationContextInitializer
Load ApplicationListener
利用Spring 工厂加载机制,实例化ApplicationLisener实现类,并实现对象集合排序
package com.yi23.backend.springboot.event.listener;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.Ordered;
/**
* hello yi23 {@link ApplicationListener} 监听 {@link ContextRefreshedEvent}事件
*
* @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang</a>
* @see
* @since
*/
public class HelloYi23ApplicationListener
implements ApplicationListener<ContextRefreshedEvent>,Ordered {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.printf("上下文内容id:%s,timestamp:%s.\r\n",
event.getApplicationContext().getId(), event.getTimestamp());
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
SpringApplication Running Stage
Load SpringApplication Run Listener
org.springframework.boot.SpringApplicationRunListeners
利用工厂加载机制,读取SpringApplicationRunListener对象集合,并封装到组合对象SpringApplicationRunListeners
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
}
Running SpringApplication Run Listeners
SpringApplicationRunListener 监听多个运行状态方法
| 监听方法 | 阶段说明 | Springboot 起始版本 |
|---|---|---|
starting |
Spring 应用刚刚启动 | 1.0 |
environmentPrepared(ConfigurableEnvironment) |
ConfigurableEnvironment准确之后,允许将其修改 |
1.0 |
contextPrepared(ConfigurableApplicationContext) |
ConfigurableApplicationContext准备之后,允许将其修改 |
1.0 |
contextLoaded(ConfigurableApplicationContext) |
ConfigurableApplicationContext已加载,但未启动 |
1.0 |
started(ConfigurableApplicationContext) |
ConfigurableApplicationContext已启动,当前Spring Bean已初始化完成 |
2.0.0 |
running(ConfigurableApplicationContext) |
Spring Application 正在运行 | 2.0.0 |
failed(ConfigurableApplicationContex,Throwable) |
Spring Application运行失败 | 2.0.0 |
Monitor Spring-Boot Event / Spring Event
SpringBoot 通过SpringApplicationRunListener的实现类EventPublishingRunListener,利用Spring Framework事件API,广播Spring Boot 事件
Spring Framework Event/Listener Model
- Spring 应用事件
- 普通应用事件:
ApplicationEvent - 应用上下文事件:
ApplicationContextEvent
- 普通应用事件:
- Spring 应用监听器
- 接口编程模型:
ApplicationListener - 注解编程模型:
@EventListener
- 接口编程模型:
- Spring 应用事件广播器
- 接口:
ApplicationEventMulticaster - 实现类:
SimpleApplicationEventMulticaster- 执行模式:同步/异步
- 接口:
EventPublishingRunListener relationship of Monitor‘s Method & Spring Boot Events
| 监听方法 | Spring Boot 事件 | Spring boot 起始版本 |
|---|---|---|
starting |
ApplicationStartingEvent |
1.5.0 |
environmentPrepared(ConfigurableEnvironment) |
ApplicationEnvironmentPreparedEvent |
1.0 |
contextPrepared(ConfigurableApplicationContext) |
||
contextLoaded(ConfigurableApplicationContext) |
ApplicationPreparedEvent |
1.0 |
started(ConfigurableApplicationContext) |
ApplicationStartedEvent |
2.0.0 |
running(ConfigurableApplicationContext) |
ApplicationReadyEvent |
1.3.0 |
failed(ConfigurableApplicationContex,Throwable) |
ApplicationFailedEvent |
1.0 |
Validate ConfigFileApplicationListener Order
package com.yi23.backend.springboot.event.listener;
import org.springframework.boot.context.config.ConfigFileApplicationListener;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.SmartApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.env.Environment;
/**
* Before {@link ConfigFileApplicationListener}
*
* @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang</a>
* @see
* @since
*/
public class BeforeConfigFileApplicationListener implements SmartApplicationListener, Ordered {
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(eventType)
|| ApplicationPreparedEvent.class.isAssignableFrom(eventType);
}
@Override
public boolean supportsSourceType(Class<?> aClass) {
return true;
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
ApplicationEnvironmentPreparedEvent environmentPreparedEvent = (ApplicationEnvironmentPreparedEvent) event;
Environment environment = environmentPreparedEvent.getEnvironment();
System.out.println("environment.getProperty(\"name\"): " + environment.getProperty("name"));
}
if (event instanceof ApplicationPreparedEvent) {
}
}
@Override
public int getOrder() {
//比 ConfigFileApplicationListener 优先级高
return ConfigFileApplicationListener.DEFAULT_ORDER - 1;
}
}
Create Spring Application Context(ConfigurableApplicationContext)
根据前面提到的Prepared 阶段推断出的Web 应用类型对应的ConfigurableApplicationContext实例:
- Web Reactive:
AnnotationConfigReactiveWebServerApplicationContext - Web Servlet:
AnnotationConfigServletWebServerApplicationContext - 非Web:
AnnotationConfigApplicationContext
/**
* Strategy method used to create the {@link ApplicationContext}. By default this
* method will respect any explicitly set application context or application context
* class before falling back to a suitable default.
* @return the application context (not yet refreshed)
* @see #setApplicationContextClass(Class)
*/
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
Create Environment
根据Prepead 阶段推断的Web应用类型创建对应的 ConfigurableEnvironment
- Web Servlet:
StandardServletEnvironment - Web Reactive:
StandardEnvironment - 非Web:
StandardEnvironment
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
if (this.webApplicationType == WebApplicationType.SERVLET) {
return new StandardServletEnvironment();
}
return new StandardEnvironment();
}
SpringBoot之SpringApplication Explain的更多相关文章
- SpringBoot之SpringApplication
简介 可以用于从java主方法中引导和启动Spring应用程序的类,在默认情况下,通过以下步骤来启动应用: 创建一个ApplicationContext实例 注册CommandLineProperty ...
- springboot自定义SpringApplication启动类
如果默认的SpringApplication不符合你的口味,你可以创建一个本地的实例并自定义它.例如,关闭banner你可以这样写: public static void main(String[] ...
- 入门到熟练-SpringBoot
Spring Boot概述 1.1. Spring Boot是什么 Spring Boot是一套基于Spring框架的微服务框架. 1.2. Spring Boot框架出现的背景 由于Spring是一 ...
- [SpringBoot guides系列翻译]调度任务
原文 调度任务 用spring实现一个任务调度. 你将做的 你将做一个应用每5秒钟打印当前时间,用@Scheduled注解. 你需要啥 15分钟 文本编辑器或者IDE JDK1.8+ Gradle4+ ...
- Spring-boot简单的理解
SpringBoot启动 SpringApplication.run(MyBootApplication.class); SpringApplication.run启动SpringBoot应用,主要过 ...
- SpringBoot入门(1)
一.初始 ①.首先还是要创建一个maven工程 ②.然后编写Controller 让SpringBoot跑起来并不需要太多的代码,就能实现了我们平时要配置很多的功能,这是怎么做到的呢?我们就下面一个入 ...
- SpringBoot 入门 Demo
SpringBoot 入门 Demo Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从 ...
- idea实现第一个springboot程序
1.环境准备 JDK:1.8 Apache Maven: 3.6.1 IntelliJ IDEA 2019.1.3 x64 SpringBoot 1.5.9.RELEASE:1.5.9: 1.1.MA ...
- 自己动手实现springboot配置(非)中心
好久没写博客了,这段时间主要是各种充电,因为前面写的一些东西,可能大家不太感兴趣或者是嫌弃没啥技术含量,所以这次特意下了一番功夫.这篇博客其实我花了周末整整两天写好了第一个版本,已经开源出去了,同样是 ...
随机推荐
- 微信小程序把玩(十一)icon组件
原文:微信小程序把玩(十一)icon组件 这些是提供的所支持的图标样式,根据需求在此基础上去修改大小和颜色. 主要属性: 使用方式: wxml <!--成功图标--> <icon t ...
- UWP-消息提示(仿Android)
原文:UWP-消息提示(仿Android) 在UWP中的消息提示框(一)中介绍了一些常见的需要用户主动去干涉的一些消息提示框,接下来打算聊聊不需要用户主动去干涉的一些消息提示框.效果就是像双击退出的那 ...
- 使用Microsoft Power BI进行基本的数据分析
Power BI是微软开发的一款简单易用的数据可视化软件. 导入数据 使用Power BI的第一步是将数据导入到软件中.获取数据->更多,可以看到可使用多种数据源,甚至微软提供了一些联机的数据源 ...
- Indy9的TIdFTPServer封装类
在Delphi 7开发下有强大的Indy控件,版本为9,要实现一个FTP服务器,参考自带的例子,发现还要写很多函数,而且不支持中文显示文件列表等等.于是,自己改进封装了下,形成一个TFTPServer ...
- 使用PNG实现半透明的窗体(使用GDI+)
Delphi中标准控件是不支持png图片的,据说从Window2000后增加gdiplus.dll库处理更多的gdi图像,其中包括png. 关键的几个api GdipCreateBitma ...
- ASP.NET Core 通过 Microsoft.DotNet.Watcher.Tools 实现热部署
之前开发前端的时候,webpack 会有热更新工具,在修改了代码之后,自动将代码编译,实时展现到页面上,给开发带来了极大的方便. Java也可以通过第三方插件JRebel实现热部署,不用频繁的重启To ...
- Docker+ Kubernetes已成为云计算的主流(二十五)
前言 最近正在抽时间编写k8s的相关教程,很是费时,等相关内容初步完成后,再和大家分享.对于k8s,还是上云更为简单.稳定并且节省成本,因此我们需要对主流云服务的容器服务进行了解,以便更好地应用于生产 ...
- 实战Java的反射机制
众所周知,Java要调用某个对象的方法首先需要对象实例化后才能调用. 而实例化对象常见的就是new执行和spring(DI)的依赖注入了. Spring的DI其实就是以反射作为最基础的技术手段. 一. ...
- 宜信开源|手把手教你安装第一个LAIN应用
LAIN是宜信公司大数据创新中心开发的开源PaaS平台.在金融的场景下,LAIN 是为解放各个团队和业务线的生产力而设计的一个云平台.LAIN 为宜信大数据创新中心各个团队提供了统一的测试和生产环境, ...
- jQuery-ajax-.get,.post方法
在上一篇中详细介绍了jQuery中ajax局部方法$.load()的使用.下面来介绍两个全局方法$.get(),$.post()的使用. 1.这两个全局方法其实和上一篇中的$.load()方法使用是差 ...