Spring Boot 项目是如何启动的?全网最细源码流程拆解

图片[1]-Spring Boot 项目是如何启动的?全网最细源码流程拆解-速优课

很多人天天在用Spring Boot,但你有没有想过一个问题:

你写的那个 main 方法,背后到底发生了什么?

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

就这一行 run(),却能完成:

  • 自动配置
  • Bean加载
  • Web容器启动
  • Spring上下文初始化

今天这篇文章,我们就把 Spring Boot 启动流程,从源码层面讲清楚。

(建议收藏,面试高频)


一、启动流程总览(先有全局观)

Spring Boot 启动大致分为5个阶段:

1、创建 SpringApplication

2、准备运行环境(Environment)

3、创建并刷新容器(ApplicationContext)

4、加载自动配置(AutoConfiguration)

5、启动内嵌 Web 服务器

核心入口就是:

SpringApplication.run()

二、第一步:创建 SpringApplication

进入源码:

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    return new SpringApplication(primarySource).run(args);
}

这里做了两件事:

1. 推断应用类型

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    return new SpringApplication(primarySource).run(args);
}

Spring Boot 会判断:

  • 是否是 Servlet 应用
  • 是否是 Reactive 应用
  • 还是普通应用

这是为什么你加个 web 依赖,就自动变成 Web 项目。


2. 加载初始化器和监听器

setInitializers(getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners(getSpringFactoriesInstances(ApplicationListener.class));

这里会读取:

META-INF/spring.factories

加载:

  • ApplicationContextInitializer
  • ApplicationListener

这也是Spring Boot“扩展能力”的核心入口。


三、第二步:运行 run() 方法核心流程

核心代码(简化版):

public ConfigurableApplicationContext run(String... args) {
    prepareEnvironment();
    createApplicationContext();
    refreshContext();
    afterRefresh();
}

1、prepareEnvironment(准备环境)

主要做:

  • 加载配置文件(application.yml / properties)
  • 解析命令行参数
  • 设置 Profile

比如:

server:
  port: 8081

就是在这里被加载的。


2、createApplicationContext(创建容器)

根据类型创建不同容器:

  • Servlet → AnnotationConfigServletWebServerApplicationContext
  • Reactive → ReactiveWebServerApplicationContext
  • 普通 → AnnotationConfigApplicationContext

本质就是创建 Spring 容器。


3、refreshContext(核心中的核心)

context.refresh();

这一行,是整个 Spring 最重要的入口!

里面会做:

✔ BeanDefinition加载

✔ Bean实例化

✔ 依赖注入

✔ AOP处理

✔ 生命周期回调

面试中,这一块是重点中的重点。


四、自动配置是怎么加载的?

关键注解:

@SpringBootApplication

它等价于:

@Configuration
@EnableAutoConfiguration
@ComponentScan

核心:@EnableAutoConfiguration

内部关键:

@Import(AutoConfigurationImportSelector.class)

AutoConfigurationImportSelector 做了什么?

它会:

从 spring.factories 中加载所有自动配置类

例如:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration

然后再根据条件注解决定是否加载:

  • @ConditionalOnClass
  • @ConditionalOnMissingBean
  • @ConditionalOnProperty

这就是:

“约定大于配置”的本质实现


五、内嵌Tomcat是怎么启动的?

在 refresh() 过程中:

onRefresh();

会调用:

createWebServer();

以 Tomcat 为例:

TomcatWebServer

Spring Boot 会:

  1. 创建 Tomcat 实例
  2. 设置端口
  3. 注册 DispatcherServlet
  4. 启动服务器

所以你根本不需要:

  • 配 web.xml
  • 配 Tomcat

一切都是自动完成的。


六、启动流程总结(重点记住这5步)

面试可以直接这样说:

1️⃣ 创建 SpringApplication

2️⃣ 加载配置环境(Environment)

3️⃣ 创建 ApplicationContext

4️⃣ 执行 refresh(初始化Bean)

5️⃣ 启动内嵌Web容器


七、面试高频问题(建议收藏)

Q1:Spring Boot自动配置原理?

答:

  • 基于 @EnableAutoConfiguration
  • 通过 spring.factories 加载配置类
  • 结合 @Conditional 条件注解实现按需加载

Q2:refresh() 做了什么?

答:

  • Bean加载
  • Bean实例化
  • 依赖注入
  • AOP
  • 生命周期管理

Q3:Spring Boot为什么开箱即用?

答:

因为自动配置 + 条件装配 + SPI机制


八、写在最后

很多人觉得Spring Boot“简单”,但其实:

简单的只是使用方式,复杂的是底层设计。

真正拉开差距的,不是你会不会用:

而是你是否理解原理。

© 版权声明
THE END
喜欢就支持一下吧
点赞6
相关推荐
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容

温馨提示:
1、本内容转载于网络,版权归原作者所有!
2、本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
3、本内容若侵犯到你的版权利益,请联系我们,会尽快给予删除处理!