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中加载一系列ApplicationContextInitializer和ApplicationListener。这些是 Spring 内部和第三方库用来在启动过程中“插手”的钩子。
第 2 步:准备环境(Environment)
- 创建环境对象:它会创建一个
Environment对象,这个对象是所有配置的汇总。 - 加载配置:它会把各种来源的配置信息加载到
Environment中,包括:- 命令行参数(
args)。 - JVM 系统属性。
- 操作系统环境变量。
application.properties或application.yml文件中的配置。- 通过
@PropertySource指定的配置文件。 - 等等…
- 命令行参数(
第 3 步:创建并准备 IoC 容器(ApplicationContext)
- 实例化容器:根据第一步推断的应用类型,Spring Boot 会创建一个合适的
ApplicationContext实例。对于 Web 应用,通常是AnnotationConfigServletWebServerApplicationContext。这个名字很长,但拆开看就是:AnnotationConfig:支持注解配置。ServletWebServer:内置了 Servlet Web 服务器(如 Tomcat)。ApplicationContext:它就是我们说的 Spring IoC 容器。
- 应用之前的准备工作:将之前准备好的
Environment、初始化器等设置到这个容器中。
第 4 步:【核心魔法】刷新容器(context.refresh())
这是整个启动过程中最重要、最复杂的一步。refresh() 方法会触发容器的一系列生命周期事件,完成 IoC 容器的初始化,其中包括了你问题的答案:
-
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文件被发现。
- 组件扫描 (Component Scan):从你的主启动类 (
-
Bean 的实例化与依赖注入:
- 容器会根据所有 Bean 的定义,开始创建它们的实例。
- 这就是“为什么一个 Web 服务会启动”的直接原因:
spring-boot-starter-web带来了 Tomcat 的 jar 包。ServletWebServerFactoryAutoConfiguration这个自动配置类被激活,因为它通过@ConditionalOnClass(Tomcat.class)检测到了 Tomcat 的存在。- 在这个配置类中,有一个用
@Bean注解的方法,它负责创建TomcatServletWebServerFactory这个 Bean。 - 当容器初始化时,它会创建这个
FactoryBean,并最终调用它的方法来创建并启动一个嵌入式的 Tomcat 服务器。
- 在创建你自己的
UserService、MyController等 Bean 时,如果发现构造函数或字段需要其他 Bean(比如UserRepository),容器就会自动从已经创建好的 Bean 仓库中找到并“注入”进去。这就是依赖注入(DI)。
第 5 步:启动后处理
- 调用 Runners:在容器完全准备好之后,Spring Boot 会寻找所有实现了
CommandLineRunner或ApplicationRunner接口的 Bean,并调用它们的run方法。这为你提供了一个在应用启动后立即执行自定义代码的机会。
总结:为什么我没写多少代码,一个 Web 服务就启动了?
可以用一个简单的公式来概括:
SpringApplication.run() = Starters + Auto-Configuration
-
Spring Boot Starters (购物清单):
- 你只需要在
pom.xml中加入spring-boot-starter-web。 - 这不仅仅是加了一个依赖,而是加了一份“搭建 Web 应用所需的全套工具和材料”的清单,包括 Spring MVC 框架、Tomcat 服务器、JSON 解析库 (Jackson) 等。它帮你管理了所有繁琐的依赖和版本。
- 你只需要在
-
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 配置和手动设置才能完成的庞大而繁琐的初始化工作。
1019

被折叠的 条评论
为什么被折叠?



