一句话定位:Spring Boot 是 Spring Framework 5.x 的上层增强层,而非替代品——它利用 Spring Framework 的 IoC、AOP、Web 等核心能力,在其之上封装了自动配置、起步依赖和运维监控,让开发者用更少代码做更多事。
定义与作用
Spring Boot 与 Spring Framework 的关系,可以类比为汽车引擎与整车的关系:Spring Framework 是高性能引擎(提供 IoC、AOP、数据访问、Web 等底层动力),Spring Boot 是围绕引擎打造的整车(提供点火启动、自动换挡、仪表盘、安全气囊等完整体验)。没有引擎,整车无法运行;没有整车,引擎需要大量手工组装才能上路。
它解决的痛点:
| 痛点 | 纯 Spring Framework 开发 | 引入 Spring Boot 后 |
|---|---|---|
| 项目初始化 | 手动创建目录结构、引入依赖、配置构建工具 | Spring Initializr 一键生成标准骨架 |
| 依赖版本管理 | 手动对齐 Spring 5.3.x + Jackson 2.13.x + Tomcat 9.x 等版本 | spring-boot-starter-parent 统一锁定兼容版本 |
| 基础设施配置 | 手写 DataSource、TransactionManager、ViewResolver 等 Bean | 自动配置根据 classpath 智能装配 |
| 部署上线 | 打包 WAR,部署到外部 Tomcat,调整 server.xml | 内嵌 Tomcat,java -jar 直接运行 |
| 生产监控 | 自行集成 Health Check、Metrics、日志采集 | Actuator 内置 /actuator/health、/actuator/metrics 等端点 |
适用位置与常用属性
本节不是讲解某个具体注解,而是厘清技术栈选型时的认知边界:
| 场景 | 应该深入 Spring Boot | 应该深入 Spring Framework |
|---|---|---|
| 自动配置不生效时排查 | ✅ 阅读 spring.factories、条件注解评估报告 | ❌ 无需深入 |
自定义 DataSource 的 Bean 被覆盖 | ✅ 理解 spring.datasource.* 配置 | ✅ 理解 @Bean 和 @ConditionalOnMissingBean |
| 事务不回滚时排查 | ❌ Spring Boot 只负责创建 TransactionManager | ✅ 理解 @Transactional 传播行为、AOP 代理机制 |
| Controller 请求参数绑定失败 | ❌ Spring Boot 只负责启动 Web 环境 | ✅ 理解 Spring MVC 的 HandlerMethodArgumentResolver |
| 循环依赖报错 | ❌ Spring Boot 不负责 | ✅ 理解 Spring Core 的 Bean 生命周期和三级缓存 |
| 自定义 Starter 开发 | ✅ 理解自动配置、条件注解、spring.factories | ✅ 理解 @Configuration、@Import、FactoryBean |
小崔在飞翔科技的学生成绩管理系统中,当遇到"数据库事务未回滚"问题时,白歌告诉他:"这不是 Spring Boot 的锅,去翻 Spring Core 的事务管理章节。"
核心原理
架构层次图
层次解读:
- 应用层:飞翔科技的开发者小崔写的业务代码、Controller、Service、以及
application.yml中的自定义配置。 - Spring Boot 增强层:自动配置负责"按需装配";Starter 负责"引入依赖套餐";Actuator 负责"暴露运行状态";外部化配置负责"从环境读取属性并覆盖默认值"。
- Spring Framework 核心层:IoC 容器负责 Bean 的实例化、依赖注入、生命周期管理(详见 Spring Core 教程);AOP 负责切面织入;Web MVC 负责请求分发;数据访问负责 JDBC 封装和事务抽象。
- 基础层:Servlet API、JDBC、Jackson 等 Java 生态基础库,Spring Framework 对其进行封装。
关系对比矩阵
完整示例
场景说明
飞翔科技的学生成绩管理系统使用 Spring Boot 2.7.18 开发。小崔好奇:"如果我不用 Spring Boot,只用 Spring Framework 5.3,这个项目会变成什么样?" 白歌让他做一个对比实验。
操作前:纯 Spring Framework 5.3 方案(无 Spring Boot)
pom.xml 依赖管理(小崔手动对齐版本):
<properties>
<spring.version>5.3.27</spring.version>
<jackson.version>2.13.5</jackson.version>
<tomcat.version>9.0.75</tomcat.version>
<hikaricp.version>4.0.3</hikaricp.version>
<mysql.version>8.0.33</mysql.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>${hikaricp.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
小崔已经手动管理了 6 个依赖的版本号,而这只是项目骨架的一半。如果升级 Spring 版本,他需要逐个检查 Jackson、Tomcat 的兼容性。
手动初始化 Tomcat 的代码:
package com.feixiang.student;
import org.apache.catalina.startup.Tomcat;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import java.io.File;
public class ManualTomcatLauncher {
public static void main(String[] args) throws Exception {
// 1. 创建内嵌 Tomcat(Spring Framework 不提供,需手动调用 Tomcat API)
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080);
tomcat.getConnector();
// 2. 创建 Spring 容器
AnnotationConfigWebApplicationContext context =
new AnnotationConfigWebApplicationContext();
context.register(AppConfig.class);
context.refresh();
// 3. 注册 DispatcherServlet
File base = new File(System.getProperty("java.io.tmpdir"));
org.apache.catalina.Context ctx = tomcat.addContext("", base.getAbsolutePath());
Tomcat.addServlet(ctx, "dispatcher", new DispatcherServlet(context));
ctx.addServletMappingDecoded("/", "dispatcher");
// 4. 启动
tomcat.start();
tomcat.getServer().await();
}
}
问题:
- 版本号手动管理,容易冲突。
- Tomcat 启动代码需要了解 Servlet API 和 Tomcat 嵌入式 API。
- 没有自动配置,DataSource、TransactionManager、Jackson 等全部需要手写
@Bean。 - 没有 Actuator,运维监控需要自行集成 Micrometer 和 Prometheus 导出器。
使用Spring Boot的完整代码
pom.xml(版本由父POM统一管理):
<?xml version="1.0" encoding="UTF-8"?>
<project>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>
<groupId>com.feixiang</groupId>
<artifactId>student-management</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>
注意:所有依赖都没有
<version>节点,spring-boot-starter-parent已锁定 Spring 5.3.27、Jackson 2.13.5、Tomcat 9.0.75、HikariCP 4.0.3 的兼容版本。
主启动类:
package com.feixiang.student;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class StudentManagementApplication {
public static void main(String[] args) {
SpringApplication.run(StudentManagementApplication.class, args);
}
}
操作后运行结果及分析
启动 Spring Boot 应用后,访问运维端点:
curl http://localhost:8080/actuator/health
响应:
{
"status": "UP",
"components": {
"db": {
"status": "UP",
"details": {
"database": "MySQL",
"validationQuery": "isValid()"
}
},
"diskSpace": {
"status": "UP"
},
"ping": {
"status": "UP"
}
}
}
分析:
- 版本管理:Spring Boot 的
spring-boot-starter-parent统一锁定了 Spring Framework、Jackson、Tomcat、HikariCP 的版本,小崔无需手动对齐。 - Tomcat 启动:
SpringApplication.run()内部自动推断应用类型为SERVLET,自动创建并启动内嵌 Tomcat,注册 DispatcherServlet,无需手写 Tomcat API。 - 自动配置:
DataSourceAutoConfiguration自动创建HikariDataSource,DataSourceTransactionManagerAutoConfiguration自动创建事务管理器。 - 运维监控:引入
spring-boot-starter-actuator后,/actuator/health自动暴露数据库连通性检查,这在纯 Spring Framework 中需要手动集成 Micrometer 和自定义 HealthIndicator。
白歌总结:"Spring Boot 省了 80% 的骨架代码,但剩下的 20% 业务逻辑和复杂问题排查,依然依赖 Spring Framework 的功底。"
易错场景与面试考点
易错场景:学习顺序颠倒,先学 Spring Boot 再补 Spring Framework
小崔入职后直接从 Spring Boot 入手,三个月后遇到以下问题:
- 自定义 Starter 失败:小崔想为飞翔科技封装一个内部日志 Starter,但不懂
@Configuration、@Import、FactoryBean等 Spring Core 机制,写出来的自动配置类无法正确加载。 - AOP 代理失效:小崔在
@Service中调用同类方法,发现@Transactional不生效,不知道这是 Spring AOP 的代理机制限制(同类自调用不走代理)。 - 循环依赖报错:Spring Boot 启动时抛出
BeanCurrentlyInCreationException,小崔只会搜索 "Spring Boot 循环依赖",却不理解 Spring Core 的三级缓存和构造器注入 vs 字段注入的区别。
错误根源:把 Spring Boot 当成独立技术学习,忽视了它是 Spring Framework 的上层封装。
正确学习路线:先建立 Spring Framework 的 IoC/AOP 基础(至少理解 Bean 生命周期、依赖注入、AOP 代理),再学 Spring Boot 的自动配置和 Starter。遇到问题时,先判断问题发生在哪一层:配置层找 Spring Boot,Bean 层找 Spring Core。
面试考点
Q:Spring Boot 和 Spring Framework 是什么关系?能否只用 Spring Boot 不用 Spring Framework?
不能。Spring Boot 是构建在 Spring Framework 之上的增强层,不是替代品。Spring Boot 的自动配置类本质上就是 Spring Framework 的
@Configuration类;SpringApplication.run()内部创建的仍然是 Spring Framework 的ApplicationContext。没有 Spring Framework,Spring Boot 无法运行。类比:Spring Framework 是引擎,Spring Boot 是整车,没有引擎整车无法行驶。
Q:Spring Boot 做了哪些 Spring Framework 没做的事?
① 版本管理:通过
spring-boot-dependenciesBOM 统一管理依赖版本,Spring Framework 不提供;② 自动配置:根据 classpath 和条件注解自动注册 Bean,Spring Framework 需要手动@Configuration;③ 内嵌容器:一键启动 Tomcat/Jetty/Undertow,Spring Framework 需要手动调用嵌入式 API;④ Actuator:内置运维监控端点,Spring Framework 需要自行集成第三方库;⑤ 外部化配置:统一的application.yml加载机制和 17 级优先级,Spring Framework 的配置加载较为分散。
Q:如果 Spring Boot 的自动配置不生效,排查思路是什么?
① 检查是否引入了正确的 Starter(如
spring-boot-starter-web);② 启动时加--debug或debug=true,查看ConditionEvaluationReport日志,看条件注解评估结果(positive matches/negative matches);③ 检查是否被@SpringBootApplication(exclude = ...)排除了;④ 检查类路径是否存在触发条件所需的类(如@ConditionalOnClass(DataSource.class)要求javax.sql.DataSource在 classpath);⑤ 如果以上都正常,深入 Spring Framework 层面检查 Bean 定义冲突或自定义配置覆盖。