您好,登录后才能下订单哦!
# SpringBoot 2.0.6的运行流程以及怎么执行SpringApplication的run方法
## 目录
1. [SpringBoot核心设计思想](#1-springboot核心设计思想)
2. [SpringApplication初始化阶段](#2-springapplication初始化阶段)
3. [run方法执行流程详解](#3-run方法执行流程详解)
- [3.1 准备环境阶段](#31-准备环境阶段)
- [3.2 创建应用上下文](#32-创建应用上下文)
- [3.3 前置处理与Bean定义加载](#33-前置处理与bean定义加载)
- [3.4 刷新应用上下文](#34-刷新应用上下文)
- [3.5 后置处理与启动完成](#35-后置处理与启动完成)
4. [关键扩展点分析](#4-关键扩展点分析)
5. [与内嵌容器的整合](#5-与内嵌容器的整合)
6. [总结](#6-总结)
---
## 1. SpringBoot核心设计思想
SpringBoot 2.0.6基于Spring Framework 5.0.10构建,其核心设计思想主要体现在三个方面:
1. **约定优于配置**:通过默认配置和自动装配机制减少XML配置
2. **内嵌容器**:集成Tomcat/Jetty等Servlet容器实现独立运行
3. **启动器(Starter)**:通过依赖管理简化第三方库集成
```java
// 典型启动类示例
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
当调用SpringApplication.run()
时,首先会执行构造方法初始化:
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 1. 设置主配置源(通常为@SpringBootApplication标注的类)
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 2. 推断Web应用类型(REACTIVE/SERVLET/NONE)
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 3. 从META-INF/spring.factories加载ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
// 4. 加载ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 5. 推断主启动类(通过堆栈分析)
this.mainApplicationClass = deduceMainApplicationClass();
}
初始化阶段关键点:
- 通过spring.factories
机制加载扩展组件
- 应用类型推断基于类路径是否存在特定类(如DispatcherHandler)
- 主类推断算法会分析调用栈找到包含main方法的类
public ConfigurableApplicationContext run(String... args) {
// 1. 创建StopWatch监控启动耗时
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 2. 配置headless模式
configureHeadlessProperty();
// 3. 获取SpringApplicationRunListeners
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
// 4. 准备环境配置
ConfigurableEnvironment environment = prepareEnvironment(listeners, args);
configureIgnoreBeanInfo(environment);
// 打印Banner
Banner printedBanner = printBanner(environment);
// 5. 创建应用上下文(根据webApplicationType)
context = createApplicationContext();
// 6. 准备异常报告器
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 7. 准备上下文
prepareContext(context, environment, listeners, printedBanner);
// 8. 刷新上下文(核心阶段)
refreshContext(context);
// 9. 后置处理
afterRefresh(context, args);
stopWatch.stop();
// 发布启动完成事件
listeners.started(context);
callRunners(context, args);
} catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
listeners.running(context);
return context;
}
根据不同的Web应用类型创建不同的上下文实现:
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_SERVLET_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) {
// 异常处理
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
AnnotationConfigServletWebServerApplicationContext
AnnotationConfigReactiveWebServerApplicationContext
AnnotationConfigApplicationContext
prepareContext()
方法完成以下工作:
ApplicationContextInitializedEvent
事件ApplicationContextInitializer
初始化逻辑ApplicationPreparedEvent
事件private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
Banner printedBanner) {
// 1. 关联环境配置
context.setEnvironment(environment);
// 2. 后置处理上下文
postProcessApplicationContext(context);
// 3. 执行初始化器
applyInitializers(context);
// 4. 触发contextPrepared事件
listeners.contextPrepared(context);
// 5. 注册启动参数bean
if (this.registerShutdownHook) {
context.registerShutdownHook();
}
// 6. 准备Bean定义加载
prepareBeanFactory(context.getBeanFactory());
}
refreshContext()
最终调用Spring Framework的AbstractApplicationContext.refresh()
:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 准备刷新(记录启动时间、状态等)
prepareRefresh();
// 2. 获取新的BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 准备BeanFactory(注册标准环境Bean等)
prepareBeanFactory(beanFactory);
try {
// 4. 后置处理BeanFactory
postProcessBeanFactory(beanFactory);
// 5. 执行BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// 7. 初始化MessageSource
initMessageSource();
// 8. 初始化事件广播器
initApplicationEventMulticaster();
// 9. 模板方法(子类实现)
onRefresh();
// 10. 注册监听器
registerListeners();
// 11. 完成BeanFactory初始化
finishBeanFactoryInitialization(beanFactory);
// 12. 完成刷新(发布ContextRefreshedEvent)
finishRefresh();
} catch (BeansException ex) {
// 异常处理...
}
}
}
SpringBoot在onRefresh()
阶段启动内嵌服务器:
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
} catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
// 从BeanFactory获取WebServerFactory
ServletWebServerFactory factory = getWebServerFactory();
// 创建WebServer(如Tomcat)
this.webServer = factory.getWebServer(getSelfInitializer());
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
} catch (ServletException ex) {
// 异常处理
}
}
initPropertySources();
}
protected void afterRefresh(ConfigurableApplicationContext context,
ApplicationArguments args) {
// 1. 执行ApplicationRunner和CommandLineRunner
callRunners(context, args);
}
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
AnnotationAwareOrderComparator.sort(runners);
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}
SpringBoot提供的主要扩展机制:
扩展点类型 | 加载时机 | 典型用途 |
---|---|---|
ApplicationContextInitializer | 上下文准备阶段 | 环境预处理、属性源配置 |
ApplicationListener | 全生命周期 | 事件监听、启动日志记录 |
BeanPostProcessor | Bean初始化阶段 | Bean代理、属性修改 |
EnvironmentPostProcessor | 环境准备阶段 | 自定义属性源加载 |
SpringApplicationRunListener | 运行过程关键节点 | 启动监控、性能统计 |
自定义扩展示例:
// 在META-INF/spring.factories中定义
org.springframework.context.ApplicationContextInitializer=\
com.example.MyInitializer
public class MyInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext context) {
// 添加自定义属性源
context.getEnvironment()
.getPropertySources()
.addLast(new MyPropertySource());
}
}
SpringBoot 2.0.6支持的内嵌容器启动流程:
ServletWebServerFactoryAutoConfiguration
配置ServerProperties
配置网络参数@AutoConfiguration
@ConditionalOnClass(Servlet.class)
@EnableConfigurationProperties(ServerProperties.class)
public class ServletWebServerFactoryAutoConfiguration {
@Bean
@ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
// Jetty和Undertow的类似配置...
}
容器启动时序图:
sequenceDiagram
participant SpringApplication
participant WebServerFactory
participant WebServer
SpringApplication->>WebServerFactory: getWebServer()
WebServerFactory->>WebServer: 创建实例
WebServer->>WebServer: 配置连接器
WebServer->>WebServer: 部署DispatcherServlet
WebServer->>WebServer: 启动线程池
WebServer-->>SpringApplication: 返回实例
SpringBoot 2.0.6的启动流程可概括为三大阶段:
环境准备阶段:
上下文创建阶段:
容器启动阶段:
关键优化点:
- 合理使用@Lazy
延迟初始化降低启动耗时
- 通过spring.autoconfigure.exclude
过滤不需要的自动配置
- 使用spring.config.location
指定外部配置提升灵活性
通过深入理解启动流程,开发者可以更好地: - 定制化SpringBoot应用启动行为 - 优化应用启动性能 - 处理复杂的初始化依赖问题 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。