面试官:SpringApplication.run(...) 这一行代码执行后,背后发生了什么?

SpringApplication.run(...) 这一行代码就像一个魔术的开关一样,按下去,整个舞台(你的应用)就搭建好了。

让我们来揭秘一下这个魔术的详细步骤。简单来说,run 方法做了一件核心大事:启动一个智能的“项目经理”(IoC 容器),让它根据“购物清单”(Starters)和“智能菜谱”(Auto-Configuration)来自动搭建和运行整个项目。

下面是这个过程的详细分解:


SpringApplication.run() 背后的核心流程

当你调用 SpringApplication.run(MyApplication.class, args) 时,Spring Boot 会依次执行以下关键步骤:

第 1 步:创建 SpringApplication 实例并进行预处理
  • 推断应用类型:Spring Boot 首先会检查你的项目依赖(classpath),来判断这是个什么样的应用。
    • 如果它找到了像 spring-webmvc 这样的依赖(通常由 spring-boot-starter-web 引入),它就会判断:“这是一个传统的 Servlet Web 应用。”
    • 如果找到了 spring-webflux,它会判断:“这是一个响应式 Web 应用。”
    • 如果都没有,它就认为这是一个普通的非 Web 应用。
  • 加载初始化器和监听器:它会从一个特殊的文件 META-INF/spring.factories 中加载一系列 ApplicationContextInitializerApplicationListener。这些是 Spring 内部和第三方库用来在启动过程中“插手”的钩子。
第 2 步:准备环境(Environment)
  • 创建环境对象:它会创建一个 Environment 对象,这个对象是所有配置的汇总。
  • 加载配置:它会把各种来源的配置信息加载到 Environment 中,包括:
    • 命令行参数(args)。
    • JVM 系统属性。
    • 操作系统环境变量。
    • application.propertiesapplication.yml 文件中的配置。
    • 通过 @PropertySource 指定的配置文件。
    • 等等…
第 3 步:创建并准备 IoC 容器(ApplicationContext
  • 实例化容器:根据第一步推断的应用类型,Spring Boot 会创建一个合适的 ApplicationContext 实例。对于 Web 应用,通常是 AnnotationConfigServletWebServerApplicationContext。这个名字很长,但拆开看就是:
    • AnnotationConfig:支持注解配置。
    • ServletWebServer:内置了 Servlet Web 服务器(如 Tomcat)。
    • ApplicationContext:它就是我们说的 Spring IoC 容器。
  • 应用之前的准备工作:将之前准备好的 Environment、初始化器等设置到这个容器中。
第 4 步:【核心魔法】刷新容器(context.refresh()

这是整个启动过程中最重要、最复杂的一步。refresh() 方法会触发容器的一系列生命周期事件,完成 IoC 容器的初始化,其中包括了你问题的答案:

  1. Bean 定义的加载

    • 组件扫描 (Component Scan):从你的主启动类 (MyApplication.class) 所在的包开始,递归扫描所有子包,寻找带有 @Component, @Service, @Repository, @RestController 等注解的类,并将它们注册为 Bean 的“定义”(可以理解为蓝图)。@SpringBootApplication 注解内部已经包含了 @ComponentScan
    • 自动配置 (Auto-Configuration):这是 Spring Boot 的王牌!它会处理所有 spring-boot-starter-* 引入的自动配置类。这些类通常位于 spring-boot-autoconfigure.jar 包中,并通过 META-INF/spring.factories 文件被发现。
  2. Bean 的实例化与依赖注入

    • 容器会根据所有 Bean 的定义,开始创建它们的实例。
    • 这就是“为什么一个 Web 服务会启动”的直接原因
      • spring-boot-starter-web 带来了 Tomcat 的 jar 包。
      • ServletWebServerFactoryAutoConfiguration 这个自动配置类被激活,因为它通过 @ConditionalOnClass(Tomcat.class) 检测到了 Tomcat 的存在。
      • 在这个配置类中,有一个用 @Bean 注解的方法,它负责创建 TomcatServletWebServerFactory 这个 Bean。
      • 当容器初始化时,它会创建这个 Factory Bean,并最终调用它的方法来创建并启动一个嵌入式的 Tomcat 服务器
    • 在创建你自己的 UserServiceMyController 等 Bean 时,如果发现构造函数或字段需要其他 Bean(比如 UserRepository),容器就会自动从已经创建好的 Bean 仓库中找到并“注入”进去。这就是依赖注入(DI)
第 5 步:启动后处理
  • 调用 Runners:在容器完全准备好之后,Spring Boot 会寻找所有实现了 CommandLineRunnerApplicationRunner 接口的 Bean,并调用它们的 run 方法。这为你提供了一个在应用启动后立即执行自定义代码的机会。

总结:为什么我没写多少代码,一个 Web 服务就启动了?

可以用一个简单的公式来概括:

SpringApplication.run() = Starters + Auto-Configuration

  1. Spring Boot Starters (购物清单)

    • 你只需要在 pom.xml 中加入 spring-boot-starter-web
    • 这不仅仅是加了一个依赖,而是加了一份“搭建 Web 应用所需的全套工具和材料”的清单,包括 Spring MVC 框架、Tomcat 服务器、JSON 解析库 (Jackson) 等。它帮你管理了所有繁琐的依赖和版本。
  2. Auto-Configuration (智能厨师)

    • @SpringBootApplication 注解开启了自动配置功能。
    • Spring Boot 就像一个聪明的厨师,它会检查你购物清单里有哪些材料(检查 classpath 上有哪些库)。
    • 它发现:“有 Tomcat 的材料。” -> 于是它自动帮你配置并启动了一个 Tomcat 服务器。
    • 它发现:“有 Jackson 的材料。” -> 于是它自动配置好了 ObjectMapper,让你的 Controller 可以直接处理 JSON。
    • 它发现:“有 Spring MVC 的材料。” -> 于是它自动配置好了 DispatcherServlet 等 Web 核心组件。

你的角色:你只需要写自己的业务逻辑(@Controller, @Service),然后通过 @Autowired(构造器注入)告诉 Spring:“我需要这些工具”,Spring IoC 容器就会把自动配置好的、或者你自己写的 Bean 准确无误地递到你手上。

所以,你写的代码虽少,但 SpringApplication.run() 这个“总开关”背后,是 Spring Boot 帮你完成了过去需要大量 XML 配置和手动设置才能完成的庞大而繁琐的初始化工作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰糖心书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值