SpringBoot 和 Spring 的区别是什么?
面试考察点
-
认知深度:面试官不仅仅是想知道 "SpringBoot 更方便" 这个表层结论,更是想看你能否讲清楚 SpringBoot 到底帮你自动做了哪些事,以及背后的原理(自动配置、起步依赖等)。
-
历史演进理解:能否说出 Spring 时代的开发痛点(配置地狱、版本冲突、手动部署),以及 SpringBoot 如何逐一解决这些痛点。
-
底层原理:能否讲清楚
@SpringBootApplication注解背后的三个核心注解、spring.factories自动配置的加载机制、内嵌 Tomcat 的启动流程。
核心答案
先说结论:SpringBoot 不是 Spring 的替代品,而是 Spring 的 "快速开发脚手架"。它底层 100% 依赖 Spring 框架,只是在 Spring 之上做了一层 "约定优于配置" 的封装,让你开箱即用。
| 对比维度 | Spring | SpringBoot |
|---|---|---|
| 核心定位 | 企业级 Java 开发框架 | Spring 的快速开发脚手架 |
| 配置方式 | 大量 XML / Java 配置 | 约定优于配置,零 XML |
| 依赖管理 | 手动管理版本,容易冲突 | 起步依赖(Starter),自动管理版本 |
| 内嵌服务器 | 无,需手动部署 WAR 到外部容器 | 内嵌 Tomcat/Jetty/Undertow,java -jar 直接运行 |
| 自动配置 | 无,手动配 Bean | 根据类路径自动装配(@EnableAutoConfiguration) |
| 生产监控 | 无内置 | Actuator 提供健康检查、指标监控 |
| 启动方式 | 部署到 Servlet 容器 | 独立运行,main() 方法启动 |
一句话总结:Spring 是引擎,SpringBoot 是带自动挡的车。引擎还是那个引擎,但不用你手动挂挡了。
深度解析
一、从 Spring 的痛点说起
没用过纯 Spring 的人可能不知道当年有多痛苦。我最早用 Spring MVC 做项目的时候,一个 web.xml 加 applicationContext.xml 能写到几百行。
Spring 时代的典型开发流程:
上面的图展示了纯 Spring 开发的典型痛点:
- 依赖版本冲突:Spring 各模块版本要自己管理,不同模块之间的版本兼容性容易出问题
- 配置地狱:光配置文件就几百行,而且每个项目都差不多,大量重复劳动
- 手动配置组件:数据源、事务管理器、视图解析器这些基础组件每次都要手动配
- 部署繁琐:打 WAR 包、部署到外部 Tomcat、处理端口冲突和类冲突
SpringBoot 的出现就是为了解决这些痛点。
二、SpringBoot 的三大核心特性
特性 1:起步依赖(Starter)
<!-- Spring 时代:手动引入一堆依赖,还要管版本 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.20</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.20</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.3</version>
</dependency>
<!-- 还要引入十几个... -->
<!-- SpringBoot:一个 Starter 搞定 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 不用写版本!parent POM 统一管理 -->
</dependency>
一个 spring-boot-starter-web 就帮你把 Spring MVC、Jackson、Tomcat、验证框架等常用依赖全引进来了,版本都帮你协调好了。
常用 Starter:
| Starter | 包含的功能 |
|---|---|
spring-boot-starter-web | Spring MVC + Tomcat + Jackson |
spring-boot-starter-data-jpa | Spring Data JPA + Hibernate |
spring-boot-starter-data-redis | Lettuce / Jedis + Spring Data Redis |
spring-boot-starter-security | Spring Security |
spring-boot-starter-test | JUnit 5 + Mockito + AssertJ |
特性 2:自动配置(Auto-Configuration)
这是 SpringBoot 最核心的特性,也是面试官最爱追问的。
@SpringBootApplication // 这个注解背后做了三件事
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
@SpringBootApplication 其实是三个注解的组合:
@SpringBootConfiguration // 本质就是 @Configuration,标记配置类
@EnableAutoConfiguration // 核心!开启自动配置
@ComponentScan // 组件扫描,扫描当前包及子包
@EnableAutoConfiguration 的原理:
上面的图展示了自动配置的核心流程:
- 第 ① 步:SpringBoot 启动时,通过
SpringFactoriesLoader扫描所有 jar 包下的META-INF/spring.factories文件(SpringBoot 3.x 改为META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports),找到所有自动配置类的全限定名。 - 第 ② 步:加载这些自动配置类,比如你引入了
spring-boot-starter-data-redis,就会加载RedisAutoConfiguration。 - 第 ③ 步:关键环节。不是所有自动配置类都会生效,每个配置类上都有
@Conditional系列注解来做条件判断。比如@ConditionalOnClass(RedisOperations.class)意味着只有类路径上有RedisOperations类时才生效。你没引入 Redis 依赖,这个配置类就会被跳过。 - 第 ④ 步:条件满足的配置类自动创建 Bean 并注册到容器中。你什么配置都不用写,Bean 就帮你配好了。
这就是 "约定优于配置" 的精髓:你引入了 Redis Starter,我就默认帮你配一个 Redis 连接工厂;你想自定义,就在 application.yml 里覆盖默认值。
特性 3:内嵌服务器
Spring 时代需要打 WAR 包部署到外部 Tomcat。SpringBoot 直接把 Tomcat 嵌入到应用里:
<!-- spring-boot-starter-web 默认内嵌 Tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 想换 Jetty?排除 Tomcat,引入 Jetty -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
启动方式:
# 打包
mvn clean package
# 一行命令启动
java -jar myapp.jar
# 指定端口
java -jar myapp.jar --server.port=8081
不需要安装 Tomcat,不需要部署 WAR 包,java -jar 一行命令搞定。这对 Docker 容器化部署极其友好。
三、SpringBoot 没有替代什么
一个常见的误区是 "SpringBoot 替代了 Spring"。不是的。
- SpringBoot 底层就是 Spring。IoC 容器、AOP、事务管理、MVC 这些核心功能全部来自 Spring 框架
- SpringBoot 只是在 Spring 之上做了一层 "自动配置 + 起步依赖 + 内嵌容器" 的封装
- 你在 SpringBoot 里用的
@Autowired、@Transactional、@RequestMapping全都是 Spring 的注解
上面的层次图说明:SpringBoot 是在 Spring 之上的一层封装,底层完全依赖 Spring。
面试高频追问
-
@SpringBootApplication注解背后做了什么?- 它是
@SpringBootConfiguration+@EnableAutoConfiguration+@ComponentScan三个注解的组合。@EnableAutoConfiguration负责加载自动配置类,@ComponentScan负责扫描当前包下的组件。
- 它是
-
SpringBoot 的自动配置原理是什么?
- 启动时通过
SpringFactoriesLoader加载META-INF/spring.factories中的自动配置类,然后根据@ConditionalOnClass、@ConditionalOnMissingBean等条件注解判断是否生效。本质是 "你引入了什么依赖,我就帮你自动配什么"。
- 启动时通过
-
SpringBoot 怎么切换内置服务器?
- 排除默认的
spring-boot-starter-tomcat,引入spring-boot-starter-jetty或spring-boot-starter-undertow即可。
- 排除默认的
-
SpringBoot 的配置文件加载顺序是什么?
application.yml/application.properties,支持多环境配置(application-dev.yml、application-prod.yml),通过spring.profiles.active激活。加载顺序:默认配置 → 应用配置 → profile 配置 → 命令行参数,后者覆盖前者。
常见面试变体
- "SpringBoot 的自动配置原理是什么?"
- "SpringBoot 的 Starter 是什么?自己写过 Starter 吗?"
- "SpringBoot 为什么不需要 XML 配置?"
- "Spring、SpringMVC、SpringBoot 之间是什么关系?"
记忆口诀
核心区别:Spring 是框架,SpringBoot 是脚手架。底层还是 Spring,上面加了一键配置。
三大特性:起步依赖管版本,自动配置省代码,内嵌容器直接跑。
自动配置本质:引入什么依赖,就帮你自动配什么;想自定义,覆盖默认值就行。
总结
Spring 和 SpringBoot 的关系是 "框架" 和 "脚手架" 的关系。SpringBoot 底层 100% 依赖 Spring,只是在上面加了起步依赖、自动配置、内嵌容器三件套。面试时先说核心区别,再展开三大特性(重点讲自动配置的 @Conditional 原理),最后强调 "SpringBoot 没有替代 Spring,只是让 Spring 用起来更简单"。这条线拉下来,面试官就清楚你是真用过,而不只是背了概念。
