SpringNotes

第 34 章:面试题精讲

zjc 于 2026-02-03 发布

这是《Spring Boot 与 Spring Cloud 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 本章整理 Spring Boot 与 Spring Cloud 高频面试题。回答时先给结论,再讲原理、场景和边界,最好结合一次真实故障或调优数据。

34.1 IoC 与 DI

问题:IoC 和 DI 是什么关系?

回答:

IoC 是设计思想:对象创建和装配的控制权交给容器。
DI 是实现方式:容器通过构造器、setter、字段等方式注入依赖。

加分点:

  1. BeanDefinition 是图纸;
  2. BeanFactory 是基础容器;
  3. ApplicationContext 增加事件、资源、环境能力;
  4. 构造器注入便于测试并暴露职责膨胀。

34.2 Bean 生命周期

问题:Bean 生命周期包含哪些阶段?

回答:

BeanDefinition 解析
  -> 实例化
  -> 属性填充
  -> Aware 回调
  -> before initialization
  -> @PostConstruct / afterPropertiesSet / initMethod
  -> after initialization
  -> Bean 就绪
  -> 销毁回调

加分点:

  1. BeanPostProcessor 是 AOP 的基础;
  2. 代理通常在初始化后生成;
  3. @PreDestroyDisposableBean、destroyMethod 的顺序;
  4. singleton 和 prototype 生命周期差异。

34.3 循环依赖

问题:Spring 如何处理循环依赖?

回答:

  1. 三级缓存针对单例 setter/字段注入;
  2. 提前暴露早期引用;
  3. 构造器循环依赖不能解决;
  4. prototype 不能解决;
  5. Spring Boot 2.6+ 默认禁止。

正确表达:

循环依赖能被机制处理,不代表设计合理。更应拆分职责、引入事件或第三方编排服务。

34.4 AOP 失效

问题:为什么 @Transactional 自调用失效?

回答:

调用方拿到的是代理对象。
代理对象进入目标对象执行 create()。
create() 内部 this.validate() 是目标对象调用,不再经过代理。

解决:

  1. 拆分 Bean;
  2. 外部调用;
  3. AopContext.currentProxy()
  4. 重新设计职责。

其他失效:

场景 原因
private 方法 代理无法拦截
final 方法 CGLIB 无法覆盖
异常被吞 拦截器看不到
受检异常 默认不回滚
多线程 事务绑定线程

34.5 Spring Boot 自动装配

问题:自动装配如何工作?

回答:

  1. @EnableAutoConfiguration 导入选择器;
  2. 读取自动配置类清单;
  3. Spring Boot 3 使用 AutoConfiguration.imports
  4. 通过条件注解过滤;
  5. @AutoConfigureBefore/After 排序;
  6. 注册 BeanDefinition。

常见条件:

@ConditionalOnClass
@ConditionalOnMissingBean
@ConditionalOnProperty
@ConditionalOnWebApplication

排查方式:--debug 输出 conditions report。

34.6 配置优先级

问题:Spring Boot 配置谁优先?

回答方向:

命令行通常优先
环境变量次之
配置中心视客户端实现
本地 profile 文件
默认配置

不要背死顺序。强调真实结果由 PropertySource 顺序决定,可用 /actuator/env 或 Environment 输出确认。

34.7 事务传播

问题:REQUIRES_NEW 和 NESTED 有什么区别?

行为 说明
REQUIRES_NEW 挂起当前事务,开启独立新事务
NESTED 在当前事务内使用保存点,局部回滚

风险:

  1. REQUIRES_NEW 占用第二个连接;
  2. 高并发可能耗尽连接池;
  3. NESTED 依赖数据库保存点支持;
  4. 外层回滚会影响嵌套事务。

34.8 Starter 设计

问题:如何设计一个 Starter?

回答:

  1. 拆分 core、api、autoconfigure、starter;
  2. 不扫描用户包;
  3. 使用 @ConfigurationProperties
  4. 条件装配提供默认 Bean;
  5. 允许用户覆盖;
  6. 提供超时和资源释放;
  7. 暴露指标和健康检查;
  8. 注册文件使用正确版本格式;
  9. 提供配置提示;
  10. 编写自动配置测试。

34.9 微服务拆分

问题:如何拆微服务?

回答框架:

1. 梳理业务流程和通用语言
2. 识别限界上下文
3. 确定数据所有权
4. 评估变更频率和团队边界
5. 从粗粒度服务开始
6. 建立契约和观测
7. 逐步独立数据库

反模式:

  1. 按技术层拆;
  2. 共享数据库;
  3. 小团队拆过多服务;
  4. 两个服务总是一起发布;
  5. 没有明确 owner。

34.10 服务发现

问题:注册中心怎么选?

回答维度:

  1. AP/CP 取舍;
  2. 健康检查模型;
  3. 多环境隔离;
  4. 权限;
  5. 运维成本;
  6. 与 K8s 或云平台集成;
  7. 团队已有生态。

关键结论:

服务发现通常偏 AP,消费者本地缓存服务列表;
即使有注册中心,也必须保留超时、重试和熔断。

34.11 网关职责

问题:网关应该做什么,不该做什么?

应该:

  1. 路由;
  2. 认证;
  3. 限流;
  4. 观测;
  5. 灰度;
  6. 安全 Header;
  7. TLS 终止。

不应该:

  1. 复杂业务规则;
  2. 数据库访问;
  3. 聚合复杂业务数据;
  4. 频繁发布的核心逻辑。

34.12 熔断限流

问题:熔断器三个状态是什么?

CLOSED -> OPEN -> HALF_OPEN -> CLOSED/OPEN

参数:

  1. 统计窗口;
  2. 最小请求数;
  3. 失败率;
  4. 慢调用比例;
  5. 打开时长;
  6. 半开探测数。

强调:

  1. 先有超时;
  2. 重试要幂等且有预算;
  3. fallback 必须记录指标;
  4. 降级要符合业务语义。

34.13 分布式事务

问题:下单跨服务如何保证一致性?

回答:

  1. 先定义状态机;
  2. 本地操作用本地事务;
  3. 事件可靠投递用 Outbox;
  4. 每一步幂等;
  5. 失败按 Saga/TCC 补偿;
  6. 定期对账;
  7. 异常进入人工处理。

不推荐只回答“用 Seata”。框架只是实现手段,业务状态和补偿设计才是核心。

34.14 优雅停机

问题:K8s 下 Spring Boot 如何无损发布?

回答:

readiness 探针摘流
  -> 收到 SIGTERM
  -> server.shutdown=graceful
  -> 停止接收新请求
  -> 等待在途请求
  -> 关闭线程池和消费者
  -> 退出

配套:

  1. preStop sleep 等摘流传播;
  2. terminationGracePeriodSeconds 大于应用等待;
  3. 消息处理完再提交 offset;
  4. 发布压测验证。

34.15 性能排查

问题:接口 P99 突然变高怎么排查?

回答:

1. 确认影响范围和时间
2. 看 QPS 和错误率
3. trace 定位慢在哪个 span
4. 检查 DB / Redis / 下游
5. 检查线程池和连接池
6. 检查 GC 和 CPU throttling
7. 关联发布和配置变更
8. 修复后验证

加分点:区分平均值和 P99,指出慢请求采样要保留。

34.16 容器内存

问题:Pod memory limit 2Gi,-Xmx 应该设多大?

回答:

不能等于 limit,因为还有:

  1. Metaspace;
  2. 线程栈;
  3. Direct memory;
  4. CodeCache;
  5. Native;
  6. OS 余量。

可用:

-XX:MaxRAMPercentage=60.0

再根据监控和 OOMKilled 情况调整。

本章小结

Spring 面试要重点讲清 IoC、Bean 生命周期、AOP、事务、自动装配、配置、Starter、微服务拆分、服务治理、分布式一致性和生产排障。高质量回答应包含场景、边界、证据和验证,而不是罗列注解。

思考题

  1. 哪些问题回答时必须说明 Spring Boot 版本?
  2. 如何用自动装配报告排查 Bean 未创建?
  3. 如何把一次事务失效讲成完整案例?
  4. 服务拆分如何证明不是过度设计?
  5. 微服务面试如何展示生产经验?