Spring Boot启动流程深度解析:从main()到应用就绪的完整旅程

1 阅读3分钟

🌱 Spring Boot启动流程深度解析:从main()到应用就绪的完整旅程

#SpringBoot核心 #启动原理 #自动配置 #源码解析


一、启动流程图解

(1) 启动类执行 → (2) SpringApplication初始化 → (3) 事件驱动模型启动  
       ↓                                        ↓  
(4) 环境准备 → (5) 应用上下文创建 → (6) Bean加载与自动配置  
       ↓                                        ↓  
(7) 执行Runners → (8) 内嵌容器启动 → (9) 应用就绪  

二、核心阶段分步详解

1. 启动入口:main方法与@SpringBootApplication

@SpringBootApplication  
public class MyApp {  
    public static void main(String[] args) {  
        SpringApplication.run(MyApp.class, args);  
    }  
}  

@SpringBootApplication 三剑客

  • @SpringBootConfiguration:标记配置类
  • @EnableAutoConfiguration:启用自动配置
  • @ComponentScan:包扫描注解

2. SpringApplication初始化

关键源码解析

// SpringApplication.java  
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {  
    return new SpringApplication(primarySources).run(args);  
}  

public SpringApplication(Class<?>... primarySources) {  
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));  
    this.webApplicationType = WebApplicationType.deduceFromClasspath();  
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));  
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));  
    this.mainApplicationClass = deduceMainApplicationClass();  
}  

初始化关键操作

  1. 推断应用类型(Servlet/Reactive)
  2. 加载META-INF/spring.factories中的初始化器和监听器
  3. 识别主配置类

3. 运行阶段:环境准备与上下文创建

3.1 环境准备
  • 加载application.properties/yml
  • 激活Profiles(spring.profiles.active
  • 配置PropertySources(命令行参数 > 系统变量 > 配置文件)
3.2 创建应用上下文

根据应用类型创建不同上下文

应用类型上下文实现类
Servlet WebAnnotationConfigServletWebServerApplicationContext
Reactive WebAnnotationConfigReactiveWebServerApplicationContext
Non-WebAnnotationConfigApplicationContext

4. 自动配置黑魔法

核心流程

1. 加载所有`META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports`  
2. 过滤排除项(@EnableAutoConfiguration.exclude)  
3. 条件注解过滤(@ConditionalOnClass等)  
4. 按@AutoConfigureOrder排序  
5. 加载有效配置类  

示例自动配置类

@AutoConfiguration  
@ConditionalOnClass(RedisTemplate.class)  
@EnableConfigurationProperties(RedisProperties.class)  
public class RedisAutoConfiguration {  
    @Bean  
    public RedisTemplate<?, ?> redisTemplate() { ... }  
}  

5. 内嵌容器启动(以Tomcat为例)

启动流程

1. 创建Tomcat实例 → 2. 初始化Connector → 3. 加载ServletContext  
4. 启动线程池 → 5. 绑定端口 → 6. 启动完成  

关键源码入口

// TomcatWebServer.java  
public void start() throws WebServerException {  
    this.tomcat.start();  
    this.startAwaitThread();  
}  

三、启动扩展点实战

1. 自定义Banner

步骤

  1. src/main/resources下创建banner.txt
  2. 使用在线生成工具设计ASCII艺术字
  3. 启用彩色输出(需配置spring.banner.charset=UTF-8

2. ApplicationRunner与CommandLineRunner

@Component  
@Order(1)  
public class MyRunner implements ApplicationRunner {  
    @Override  
    public void run(ApplicationArguments args) {  
        System.out.println("应用启动后执行");  
    }  
}  

执行顺序CommandLineRunnerApplicationRunner(同Order值下)

3. 自定义事件监听

@Component  
public class MyListener implements ApplicationListener<ApplicationReadyEvent> {  
    @Override  
    public void onApplicationEvent(ApplicationReadyEvent event) {  
        System.out.println("应用已就绪");  
    }  
}  

四、启动优化技巧

1. 延迟初始化

# application.properties  
spring.main.lazy-initialization=true  

优点:加快启动速度 缺点:首次请求可能变慢

2. 排除自动配置

@SpringBootApplication(exclude = {  
    DataSourceAutoConfiguration.class,  
    RedisAutoConfiguration.class  
})  

3. 日志级别控制

logging.level.root=WARN  
logging.level.org.springframework=ERROR  

五、启动问题排查指南

1. 常见启动错误

异常类型常见原因
BeanCurrentlyInCreationException循环依赖
PortInUseException端口被占用
NoSuchBeanDefinitionException未正确扫描包

2. 诊断工具

  • 启动日志分析--debug参数输出自动配置报告
  • 线程Dumpjstack <pid> > thread.txt
  • 内存分析jmap -dump:format=b,file=heap.hprof <pid>

六、Spring Boot启动全景图

[启动类]  
  │  
  ├─> 初始化SpringApplication  
  │    ├─> 推断Web类型  
  │    ├─> 加载初始化器/监听器  
  │    └─> 识别主配置类  
  │  
  ├─> 运行阶段  
  │    ├─> 准备Environment  
  │    ├─> 创建ApplicationContext  
  │    ├─> 刷新上下文(Bean加载、自动配置)  
  │    ├─> 执行Runners  
  │    └─> 启动内嵌容器  
  │  
  └─> 发送ApplicationReadyEvent  

掌握Spring Boot启动流程,助您从容应对复杂项目初始化问题! 🚀