SpringBoot之SpringApplication Explain
SpringApplication Explain
The
SpringApplication
class provides a convenient way to bootstrap a Spring application that is started from amain()
method. In many situations, you can delegate to the staticSpringApplication.run
method, 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
UseSpringApplication
API 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中的推断实现
![image-20190306144854302](/Users/zhangpan/Library/Application Support/typora-user-images/image-20190306144854302.png)
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配置(非)中心
好久没写博客了,这段时间主要是各种充电,因为前面写的一些东西,可能大家不太感兴趣或者是嫌弃没啥技术含量,所以这次特意下了一番功夫.这篇博客其实我花了周末整整两天写好了第一个版本,已经开源出去了,同样是 ...
随机推荐
- 零元学Expression Blend 4 - Chapter 26 教你如何使用RaidoButton以及布局容器的活用
原文:零元学Expression Blend 4 - Chapter 26 教你如何使用RaidoButton以及布局容器的活用 本章将教大家如何运用Blend的内建元件RaidoButton做出选单 ...
- Android Studio 添加 Genymotion插件
原文:Android Studio 添加 Genymotion插件 1.下载Genymotion:官网地址,必须先注册才能下载,下载带有VirtualBox的版本 2.安装:安装时会连VirtualB ...
- ASP.NET MVC控制器Controller中参数
前述文章参见:ASP.NET MVC控制器Controller 绪论 之前的控制器返回的均为常量字符串,接下来展示如何获取请求传来的参数,而返回"动态"的字符串. 可以在操作方法B ...
- Qt4.8.6详细安装步骤(使用了i686-4.8.2-release-posix-dwarf-rt_v3-rev3,手动设置gcc和gdb)非常清楚 good
摘要 在网上查看了很多篇关于Qt 4的安装方法,都是以前很久的帖子,所以就想按自己的方式重新总结一下,希望可以帮助到大家. Qt5的安装比较简单只需要下载一个文件qt-opensource-windo ...
- T4生成整理
将一些公用的东西弄到一个类库DM.T4里面,哪个项目需要用到t4生成的话,将DM.T4的生成事件中将dll和ModelAuto.ttinclude复制到需要使用T4的项目的生成目录下,如果这样 cop ...
- 关于Windows更新窗口内容的问题(作为一个实验,效果很明显)
Windows中的窗口在特定情况下会由系统进行重绘,如无效区域重新显现时,,会向窗口的处理过程发送VM_PAINT消息,但是,可能还有Windows自己的更新窗口处理,如在下面的代码中,将击键显式地转 ...
- Windows下获取逻辑cpu数量和cpu核数量(用GetLogicalProcessorInformation,从XP3才开始有的API)
代码可在Windows NT下正常运行 具体API说明请参照如下文档: GetLogicalProcessorInformation 点击打开链接 点击打开链接 点击打开链接 typedef BOOL ...
- 浅谈stylus与sass的对比
all we konw , 这两个都是css的预编译工具,但虽然都是编译工具,但还是存在差别的,下面来讲讲其中的区别 1.变量 sass定义变量是以这种形式进行定义的$xxx:10;而stylus的定 ...
- List集合总结,对比分析ArrayList,Vector,LinkedList
前面已经写了三篇关于Java集合的文章,包括: Java集合 ArrayList原理及使用 再说Java集合,subList之于ArrayList Java集合 LinkedList的原理及使用 关于 ...
- AppBoxFuture: 大数据表分区的3种策略
之前的文章"分而治之"在介绍大表分区时,作者尚未实现不同的分区策略,即只能按指定的分区键进行分区.这次作者完善了一下分区策略,在规划大表分区时可以按Hash或者时间范围进行分区 ...