Starter 的魔力: 为什么我只是在 pom.xml 中加入了 spring-boot-starter-web,就能直接注入 TomcatWebServer 等复杂的对象?

想要回答这个问题,我们必须先了解 Spring Boot 最核心的“魔法”——Starter 依赖自动配置(Auto-Configuration)

让我们一步步拆解这个“魔法”。

魔法的核心:我们用一个“智能工具箱”来描述这个问题

你可以把 spring-boot-starter-web 想象成一个**“Web 开发智能工具箱”**。

  1. 你买来工具箱(添加依赖):你在 pom.xml 中加入 spring-boot-starter-web

  2. 工具箱里有什么?:这个箱子本身是空的,但它贴了一张“清单”,上面写着:

    • 一套“Web 框架工具”(spring-webmvc
    • 一个“嵌入式服务器”(默认是 tomcat-embed-core
    • 一套“JSON 处理工具”(jackson-databind
    • …以及其他所有Web开发必需的工具。
      Maven/Gradle 看到这个清单,就会自动把所有这些“工具”(JAR包)下载到你的项目中。
  3. 你的项目有了新“能力”:现在,你的项目“工具架”(classpath)上,已经摆满了 Web 开发所需的所有工具。

  4. 智能总开关启动(自动配置):Spring Boot 启动时,它的**自动配置(Auto-Configuration)**模块就像一个超级智能的机器人管家,它会扫描你项目里所有的“工具”。

    • 它看到架子上有 Tomcat 的工具(tomcat-embed-core.jar)。
    • 它心想:“哦!主人想做一个 Web 应用,而且他准备了 Tomcat。那我就得帮他把这个 Tomcat 服务器启动起来,并配置好。”

这个“智能机器人管家”就是 Spring Boot 的自动配置机制。


揭秘流水线:从依赖到可用的 Bean

整个过程可以分为四个关键步骤:

第一步:Starter 引入依赖集合

正如比喻中所说,spring-boot-starter-web 本身几乎没有代码,它的主要作用是通过 Maven/Gradle 的传递性依赖,一次性地将所有相关的库都引入到你的项目中。

spring-boot-starter-web -> 引入 -> spring-webmvc, spring-web, tomcat-embed-core, jackson-databind 等。

结果:你的项目 classpath 上现在有了 Tomcat 相关的类。这是后续所有魔法的前提

第二步:@EnableAutoConfiguration 扫描 Classpath

还记得主启动类上的 @SpringBootApplication 吗?它内部包含了一个关键注解:@EnableAutoConfiguration

这个注解告诉 Spring Boot:“请开启你的‘智能管家’模式!”

这个“智能管家”在启动时,会去一个特定的地方查找一份**“配置说明书”**。这份说明书在 Spring Boot 2.7 之前是 META-INF/spring.factories 文件,之后是 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件。

spring-boot-autoconfigure.jar 这个核心包里,这份说明书列出了所有可能的自动配置类,比如:

  • org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
  • org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
  • org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
  • …等等,足足有上百个。
第三步:“条件化配置”进行智能判断

Spring Boot 不会愚蠢地加载所有这些配置类。每个自动配置类都是一个“聪明”的 @Configuration 类,它们身上都带有条件注解(@Conditional...

让我们聚焦到与 Tomcat 相关的 ServletWebServerFactoryAutoConfiguration 这个类,它的代码(简化后)大致是这样的:

@Configuration
// 条件1:只有当这是一个Servlet Web应用时,此配置才生效
@ConditionalOnWebApplication(type = Type.SERVLET) 
public class ServletWebServerFactoryAutoConfiguration {

    @Configuration
    // 条件2:只有当classpath上存在 Tomcat 的类时,此内部配置才生效
    @ConditionalOnClass({ "com.launchdarkly.shaded.org.apache.catalina.startup.Tomcat" })
    // 条件3:只有当容器里还没有任何 ServletWebServerFactory 类型的Bean时,此配置才生效
    @ConditionalOnMissingBean(ServletWebServerFactory.class) 
    static class EmbeddedTomcat {

        @Bean
        // 如果以上所有条件都满足,就创建这个 Tomcat 工厂 Bean!
        public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
            return new TomcatServletWebServerFactory();
        }
    }

    // (类似的,还有用于Jetty和Undertow的配置,也带有 @ConditionalOnClass 注解)
}

智能判断流程如下:

  1. Spring Boot:我要不要加载 ServletWebServerFactoryAutoConfiguration
  2. @ConditionalOnWebApplication:检查发现,嗯,spring-webmvc 在,是个 Web 应用。通过!
  3. Spring Boot:我要不要加载里面的 EmbeddedTomcat 内部配置类?
  4. @ConditionalOnClass:检查 classpath,发现 tomcat-embed-core.jar 里的 Tomcat 类确实存在。通过!
  5. @ConditionalOnMissingBean:检查 IoC 容器,发现还没有人定义 ServletWebServerFactory 这种 Bean。通过!

所有条件都满足了!于是,Spring Boot 就会执行 @Bean 注解的 tomcatServletWebServerFactory() 方法。

第四步:创建并注册 Bean 到 IoC 容器

tomcatServletWebServerFactory() 方法被执行,它 new 了一个 TomcatServletWebServerFactory 对象。这个对象就是一个专门用来创建和配置嵌入式 Tomcat 服务器的工厂。

Spring Boot 将这个工厂对象作为一个 Bean 注册到了 IoC 容器中。

后续,Spring Boot 的其他自动配置(比如 DispatcherServletAutoConfiguration)会从容器中获取这个工厂 Bean,并使用它来创建、配置并启动一个真正的 TomcatWebServer 实例。这个 TomcatWebServer 实例最终也成为了一个 Bean。

所以,当你需要注入 TomcatWebServer 时(虽然一般不这么做),IoC 容器里已经有了一个现成的、由自动配置流水线为你精心打造的实例了。

总结

你做的(You Do)Spring Boot 做的(Spring Boot Does)
1. 在 pom.xml 中添加 spring-boot-starter-web1. 传递性依赖:下载 tomcat-embed-core.jar 等一系列 JAR 包到 classpath。
2. 运行带有 @SpringBootApplication 的主类。2. 启用自动配置@EnableAutoConfiguration 开始工作。
3. 加载配置清单:读取 ...autoconfigure.AutoConfiguration.imports 文件,得到一个候选配置列表。
4. 条件化判断:逐一检查候选配置。发现 classpath 上有 Tomcat 的类,且用户没有自定义服务器工厂,于是 ServletWebServerFactoryAutoConfiguration 中的条件成立。
5. 创建和注册 Bean:执行 @Bean 方法,创建 TomcatServletWebServerFactory 等一系列与 Web 服务器相关的 Bean,并放入 IoC 容器。
3. 在你的代码里用 @Autowired 注入一个 ... 对象。6. 依赖注入:从 IoC 容器中找到已经创建好的 Bean,注入到你的类中。

这就是 Starter 的魔力:它通过一个简单的依赖,触发了一套强大、智能、且按需装配的自动化配置流水线,将复杂的组件初始化和集成工作完全自动化,让开发者可以开箱即用。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

冰糖心书房

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

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

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

打赏作者

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

抵扣说明:

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

余额充值