Spring Boot 常见面试题
问题
Spring Boot 面试中还有哪些高频问题?
答案
本文汇总 Spring Boot 面试中的其他高频问题,补充已有文档未覆盖的知识点。
Spring Boot 启动流程
启动后执行逻辑
CommandLineRunner & ApplicationRunner
// 方式1:CommandLineRunner(参数是 String[])
@Component
@Order(1) // 控制执行顺序
public class DataInitRunner implements CommandLineRunner {
@Override
public void run(String... args) {
// 应用启动后执行:初始化数据、预热缓存等
}
}
// 方式2:ApplicationRunner(参数是 ApplicationArguments,更结构化)
@Component
@Order(2)
public class CacheWarmRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) {
// args.getOptionValues("name") 可获取 --name=value 参数
}
}
Spring Boot 与 Spring 的区别
| 对比 | Spring | Spring Boot |
|---|---|---|
| 配置 | 大量 XML 或 Java Config | 自动配置 + 约定优于配置 |
| 依赖管理 | 手动管理每个依赖版本 | Starter 统一管理 |
| 服务器 | 需要外部 Tomcat | 内嵌服务器 |
| 部署 | WAR 包 | 可执行 JAR |
| 监控 | 需要自行集成 | Actuator 开箱即用 |
| 上手难度 | 较高 | 快速上手 |
本质关系
Spring Boot 不是新框架,而是 Spring 的脚手架。它简化了 Spring 应用的搭建和配置,核心功能(IoC、AOP、事务等)全部来自 Spring Framework。
日志框架
Spring Boot 默认使用 SLF4J + Logback:
application.yml
logging:
level:
root: INFO
com.example.service: DEBUG # 指定包的日志级别
org.springframework.web: WARN
file:
name: logs/app.log # 日志文件路径
logback:
rollingpolicy:
max-file-size: 100MB # 单文件大小
max-history: 30 # 保留天数
pattern:
console: "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
全局异常处理
GlobalExceptionHandler.java
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Result<?>> handleValidation(MethodArgumentNotValidException e) {
String msg = e.getBindingResult().getFieldErrors().stream()
.map(err -> err.getField() + ": " + err.getDefaultMessage())
.collect(Collectors.joining("; "));
return ResponseEntity.badRequest().body(Result.fail(400, msg));
}
@ExceptionHandler(Exception.class)
public ResponseEntity<Result<?>> handleException(Exception e) {
log.error("系统异常", e);
return ResponseEntity.status(500).body(Result.fail(500, "系统繁忙"));
}
}
// 统一响应格式
public record Result<T>(int code, String message, T data) {
public static <T> Result<T> ok(T data) { return new Result<>(200, "success", data); }
public static <T> Result<T> fail(int code, String msg) { return new Result<>(code, msg, null); }
}
跨域处理
全局 CORS 配置
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://example.com")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}
Spring Boot 测试
单元测试 + 集成测试
// 集成测试:启动完整的 Spring 上下文
@SpringBootTest
class OrderServiceTest {
@Autowired
private OrderService orderService;
@MockBean // Mock 掉外部依赖
private PaymentClient paymentClient;
@Test
void createOrder_success() {
when(paymentClient.charge(any())).thenReturn(PayResult.success());
Order order = orderService.createOrder(new OrderDTO("item-1", 100));
assertThat(order.getStatus()).isEqualTo("PAID");
}
}
// Controller 层测试:只加载 Web 层
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void getUser_returnsUser() throws Exception {
when(userService.findById(1L)).thenReturn(new User(1L, "Alice"));
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Alice"));
}
}
常见面试问题
Q1: Spring Boot 的启动流程?
答案:
main()调用SpringApplication.run()- 推断应用类型(Servlet/Reactive)
- 加载
ApplicationContextInitializer和ApplicationListener - 创建
Environment,加载配置文件 - 打印 Banner
- 创建
ApplicationContext refreshContext():扫描 Bean 定义、创建 Bean、启动内嵌 Web 服务器- 执行
CommandLineRunner/ApplicationRunner
Q2: Spring Boot 和 Spring 的区别?
答案:
Spring Boot 是 Spring 的脚手架,核心功能来自 Spring。它提供自动配置(减少手动配置)、Starter(简化依赖管理)、内嵌服务器(简化部署)、Actuator(生产监控)。开发者只需关注业务逻辑,Spring Boot 处理基础设施。
Q3: 如何实现 Spring Boot 应用的热部署?
答案:
开发环境使用 spring-boot-devtools:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
它会在代码变更后自动重启应用(使用两个 ClassLoader,只重新加载用户类)。生产环境不要使用。
Q4: @SpringBootApplication 包含哪些注解?
答案:
@SpringBootApplication = @SpringBootConfiguration(配置类) + @EnableAutoConfiguration(自动配置) + @ComponentScan(包扫描)。
Q5: Spring Boot 如何实现统一响应格式?
答案:
// 方式1:封装 Result 类 + 手动包装
public Result<User> getUser() {
return Result.ok(userService.findById(id));
}
// 方式2:ResponseBodyAdvice(全局自动包装)
@RestControllerAdvice
public class ResponseWrapper implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(...) { return true; }
@Override
public Object beforeBodyWrite(Object body, ...) {
if (body instanceof Result) return body;
return Result.ok(body);
}
}
Q6: Spring Boot 打成 JAR 和 WAR 的区别?
答案:
- JAR(默认):内嵌服务器,
java -jar直接运行。适合微服务和容器化部署 - WAR:需部署到外部 Tomcat。适合传统部署方式或需要和其他应用共享 Tomcat
一般推荐 JAR 方式,除非有特殊的运维要求必须使用外部 Tomcat。
相关链接
- Spring Boot 官方文档
- 自动配置原理 - @EnableAutoConfiguration
- Starter 机制 - Starter 原理与自定义
- 配置管理 - 配置优先级与多环境
- Actuator 监控 - 健康检查与指标
- 内嵌服务器 - 服务器原理与调优
- Spring MVC - 请求处理流程