07小节:什么是SpringBoot-Starter?
作者:程序员马丁
热门项目实战社群,收获国内众多知名公司面试青睐,近千名同学面试成功!助力你在校招或 社招上拿个offer。
什么是SpringBoot-Starter?元数据信息:
- 什么是线程池oneThread:https://t.zsxq.com/5GfrN
- 代码仓库:https://gitcode.net/nageoffer/onethread —— 申请项目权限参考上述线程池项目链接
- 章节难度:★★☆☆☆ - 中等
- 视频地址:本章节内容简单,无
©版权所有 - 拿个offer-开源&项目实战星球专属学习项目,依据《中华人民共和国著作权法实施条例》和《知识星球产权保护》,严禁未经本项目原作者明确书面授权擅自分享至 GitHub、Gitee 等任何开放平台。违者将面临法律追究。
内容摘要:SpringBoot Starter 就像开发者的贴心“料理包”——一行依赖,配料齐全,配置就绪,让你从此告别东拼西凑,专注业务本味。
课程目录如下所示:
- 引子:SpringBoot 的“小帮手”
- Starter 核心原理揭秘
- 为什么会有 Starter?解决了哪些问题?
- SpringBoot 2.x 与 3.x Starter 机制对比
- 常用的 SpringBoot 官方 Starters 列表
- 最小可运行的自定义 Starter 示例
- 文末总结
引子:SpringBoot 的“小帮手”
试想一下,在传统开发中我们要使用某个框架功能(比如数据库访问或消息队列),常常需要东拼西凑地添加一堆依赖,还要配置各种参数。这就像下厨做菜前,还得满世界找食材、调料,步骤繁琐又容易出错。而 Spring Boot Starter(启动器)就像一个贴心的“大厨助手”或 预先配好的料理包,帮我们一次性备齐所需“食材”(依赖)和默认配置,让开发者开箱即用,少操很多心。Spring Boot Starter 用轻松的话来说,就是 Spring Boot 世界里的“小帮手”,只要把它引入项目,它就会自动帮你准备好相关技术栈需要的各种依赖,并且偷偷帮你做好配置工作。结果就是,你只需要专注于业务逻辑,许多底层繁琐的配置都被默默安排妥当了。
举个例子,之前如果想要让项目具备 Web 服务能力,需要引入以下依赖。你开始迷茫:这么多依赖,我到底应该用哪个?为什么我需要记住这么多东西?
事实上,在 Spring Boot 出现之前,这种“选择困难症”确实困扰了很多人,包括我。正经人谁会记那么多依赖地址呢。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.x.x.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.x.x.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.x.x.RELEASE</version>
</dependency>
为了解决这个问题,Spring 团队给出了一个非常人性化的方案:Spring Boot Starter。
用大白话讲,Starter 就像是一个礼盒。里面装好了你想要的所有东西(依赖和配置),你只需要一个依赖,整个功能全都给你安排妥当。想用 Web 功能吗?加上一个依赖就行了:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
发现什么了吗?没错,甚至连版本号都不需要写,因为 SpringBoot 已经帮你统一管理了。
Starter 背景与作用
在没有 SpringBoot 的年代,引入第三方组件通常意味着要在 Maven/Gradle 里添加多个坐标依赖,然后再去查文档写大量配置文件,非常麻烦**(依赖版本不匹配、配置分散各处都是常见痛点)**。SpringBoot 提出了“约定优于配置”的理念,Starters 正是这一理念的产物。Starter 的作用简单来说有以下几点:
1. 依赖管理一站式
一个 Starter 包含了一组相关的依赖,就像“自助套餐”。你加上一个 Starter,相当于引入了一系列经过官方测试搭配好的依赖,避免了自己挨个寻找版本兼容的库。例如,要使用 Spring Data JPA 访问数据库,只需添加 spring-boot-starter-data-jpa
,它会自动引入 Spring Data JPA、Hibernate 以及数据库连接池等必要组件。不再需要东翻西找依赖,一个 Starter 就帮你打包好了所有常用库。
2. 自动配置减负
Starter 配合 Spring Boot 的自动装配机制,能够根据类路径上的依赖自动进行默认配置。这意味着许多以前需要写的样板配置代码,现在 Spring Boot 会替你完成。例如,引入 spring-boot-starter-web
后,由于类路径有 Spring MVC 和 Tomcat,应用启动时会自动配置好 DispatcherServlet、嵌入式 Tomcat 容器等,开发者无需再写XML或@Bean去配置这些。Starter 大大减少了配置分散的问题,将繁琐的配置集中在框架内部约定好,让我们专注于少量必要的属性调整即可。
3. 开箱即用的默认
大多数 Starter 都提供了一套合理的默认行为。例如 spring-boot-starter-logging
会默认使用 Logback 日志框架,spring-boot-starter-web
默认使用 Tomcat 容器并开启 Spring MVC。这些默认配置遵循官方最佳实践,避免了开发者从零开始配置。同时如果默认不符合要求,我们仍可以通过 application.properties/yaml 来微调参数,Spring Boot 会自动将配置绑定到对应组件。可以说,Starter 实现了“约定优于配置”:在有合理默认的前提下,减少开发者的选择成本和配置工作量。
概括来说,Spring Boot Starter 的出现解决了依赖管理杂乱和配置碎片化的问题。过去可能我们需要拷贝粘贴各种依赖坐标、写很多配置,现在只需引入一个 Starter,绝大部分配置就帮你默默搞定。这也是为什么 Spring Boot 能让项目搭建变得如此简单快速的关键原因之一。
Starter 核 心原理揭秘
Starters 之所以能做到“引入即用”,背后离不开 Spring Boot 自动装配(Auto-Configuration)机制 的支撑。下面让我们以拟人化的方式,跟随 Spring Boot 的启动流程,看看 Starter 是如何把相应功能自动注入到应用中的:
当我们在主应用类上标注了 @SpringBootApplication
(其内部含有@EnableAutoConfiguration
注解)时,Spring Boot 会在启动时做如下事情:
1. 搜集候选自动配置类
Spring Boot 利用 SpringFactoriesLoader
去扫描应用类路径下所有 JAR 包里的特殊配置文件。对于 Spring Boot 2.x,这个文件就是每个 Starter JAR 中 META-INF/spring.factories
;而在 Spring Boot 3.x,这个机制有所改变,变成在每个 Starter JAR 中查找 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件。这两个文件本质上都是列出该 Starter 提供的自动配置类列表。比如在 Spring Boot 2.x,一个 Starter 可能在 spring.factories
中声明:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.MyFeatureAutoConfiguration
Spring Boot 读取到这个条目,就知道这个 Starter 包含 MyFeatureAutoConfiguration
这个自动配置类需要被加载。而在 Spring Boot 3.x,我们不再使用键值对配置,而是直接在 AutoConfiguration.imports
文件里逐行列出自动配置类全限定名,例如:
com.example.MyFeatureAutoConfiguration
com.example.AnotherAutoConfiguration
Spring Boot 3.x 会扫描 META-INF/spring/*.imports
目录下的文件来收集自动配置类名单。这一新机制更简单直观,每行一个类名,不需要再像旧格式那样写键值对,性能和模块化也有所提升。无论新旧版本,此步骤的结果都是:根据所有引入的 Starter,Spring Boot 得到了一张“需要尝试自动配置的配置类清单”。
2. 按条件装配自动配置类
拿到所有候选的自动配置类名后(可能成百上千个),SpringBoot 并不会傻乎乎地把它们统统装配进来,而是会挨个筛选,判断条件是否满足。这得益于 SpringBoot 提供的一系列条件注解,常用的如:
@ConditionalOnClass
:当类路径下存在某个类时才生效。@ConditionalOnMissingClass
:缺少某类时生效。@ConditionalOnBean
:当容器中已有某个 Bean 时/不在时生效。@ConditionalOnProperty
:当配置文件中某个属性有指定值时生效等等。
这些条件注解被广泛地应用在各个自动配置类上,用于细粒度地控制配置是否需要自动装配。
其中最重要的一个条件是 @ConditionalOnMissingBean
。它表示“仅当容器中没有某个特定类型的 Bean时,才执行自动配置”。这确保了当开发者自己定义了同类型的 Bean 时,自动配置会“知趣地”退让,不会再创建重复的默认Bean。
例如,SpringBoot 会在 JDBC 数据源的自动配置类中用 @ConditionalOnMissingBean(DataSource.class)
判断,如果你已经手动提供了一个 DataSource
Bean,那么默认的自动配置 DataSource 就不会再生效。这种机制保证了 Starter 提供默认配置的同时,不会妨碍你去覆盖/自定义配置。
小科普:SpringBoot 为了提升启动效率,甚至会在应用启动早期就利用注解处理器预先生成一份关于条件注解的元数据 (
META-INF/spring-autoconfigure-metadata.properties
)。这样在真正逐个评估条件前,可以快速跳过一些明显不满足条件的自动配置,从而加快启动。总之,条件装配机制让自动配置更加智能和高效。
3. 注册 Bean 到容器
通过条件筛选后,符合条件的自动配置类会被实例化并发挥作用。其实每个自动配置类本质上就是一个加了 @Configuration
注解的普通 Spring 配置类,其中定义了一系列 @Bean
方法用于注册组件。例如,WebMvcAutoConfiguration
会注册 DispatcherServlet、HandlerMapping、HttpMessageConverters 等 Web 开发需要的组件;DataSourceAutoConfiguration
会创建数据源连接池 Bean 等等。一旦这些配置类被加载,其内部定义的 Bean 就会按照 Spring 容器的规则被注册。
至此,原本我们需要手工配置的许多 Bean,因为 Starter 的引入而在后台自动完成注册了。
综上所述,SpringBoot Starter 能够自动注入所需功能,完全是托管于 Spring Boot 自动装配机制。Starters 本身通常并不包含太多代码(很多官方 Starter 甚至只是一个 POM 依赖集合),但它们的存在触发了 SpringBoot 去加载对应的 AutoConfiguration 配置模块。
总之,Starter 和自动装配是一对好搭档:Starter 提供依赖和入口,自动装配提供智能配置逻辑,两者结合使得 SpringBoot 应用具有开箱即用的特性。
为什么会有 Starter?解决了哪些问题?
通过上面的介绍,相信大家已经体会到 Starter 带来的诸多便利。这里我们再总结提升一下,Spring Boot Starter 的诞生究竟解决了哪些过去的痛点:
1. 依赖版本冲突与管理
在大型项目中,手动管理众多库的版本很容易掉坑,不同库之间版本不兼容会导致 ClassNotFound 或 NoSuchMethod 错误。Starter 通常由 Spring 官方或第三方维护者出品,他们在 Starter 的依赖里锁定了兼容的版本组合(SpringBoot 本身还有一个版本对齐的 BOM 管理所有 Starter 依赖版本)。这意味着只要我们选定了一个 SpringBoot 版本,对应的官方 Starters 都有合理的依赖版本,不用自己纠结选哪个版本的驱动、哪版客户端库,这极大减少了版本冲突的风险。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2. 繁杂配置的标准化
没有 Starter 时,不同第三方组件的整合各有 各的配置方法,项目中可能散落着 XML、properties、Java Config,多处修改才能完成一个组件的接入。这种配置分散不仅增加了初始集成难度,也给后期维护带来麻烦(要记得修改多处地方)。
Starter 则提供了统一的引入方式:约定大多数配置通过应用的 application.properties/yml
来集中管理,尽量减少散弹枪式的配置方式。例如,引入 spring-boot-starter-redis
后,你只需在 application.yml 配置 Redis 的地址和少量参数,Starter 已经让 Redis 客户端和Template等Bean完成自动注入,比起手动编写@Configuration去创建Jedis连接工厂之类要省事得多。配置集中、约定统一提升了可维护性。
3. 开发效率和学习成本
Starter 让常用技术栈变得傻瓜化。新手可能不知道“我要用Web服务需要哪些依赖?需要配置什么Servlet?”,但他只要知道选择 spring-boot-starter-web
就够了。Starter 隐藏了复杂性,提供了友好的学习曲线:开发者可以先用默认配置跑通功能,然后再逐步了解如何自定义。没有 Starter 的年代,搭建环境本身就可能耗费大量时间和精力,现在这些都由 Starter 替我们做了底层重活累活。
可以说,Starter 促进了Spring生态的一键集成,降低了各项技术的上手门槛。
4. 约定优于配置的贯彻
Spring Boot 崇尚约定优于配置,Starter 是这种哲学的具体体现。它通过约定好的依赖和默认行为让我们“省心”。例如 Spring Boot 约定了常用框架的默认端口、默认编码、默认日志级别等等,这些约定很多是通过各 Starter 的自动配置实现的。如果没有 Starter,每个项目可能各自为政,开发者自己去配置这些参数。而 Starter 保证了大家不做特别配置时就能有一致的行为,这对团队协作和开源项目来说都是很重要的(减少“它在我电脑上跑不通”的情况)。因此,Starter 的出现也减少了配置错误的可能,把最佳实践内置在框架中。
总之,Spring Boot Starter 之所以“香”,正因为它极大地简化了依赖管理与配置工作,解决了过去开发中常见的痛点,让我们更聚焦于业务本身。Starter 带来的这一系列好处,正是 SpringBoot 能流行的一个关键原因。
SpringBoot 2.x 与 3.x Starter 机制对比
Spring Boot 3.x 相对于 2.x 对 Starter(主要是自动配置加载机制)做出了一些改进和变化。理解这些差异有助于我们在不同版本下编写和使用 Starter。下面我们来对比一下: