Skip to content

Java 17 与 Spring Boot 3.x 面试题

本页只保留面试标准回答、追问和原理页跳转。详细推导请进入对应知识点页。

1. Spring Boot 2.7 与 3.x 的核心区别是什么

标准回答: Boot 2.7 常见基线是 Java 8、Spring Framework 5.3 和 javax 规范;Boot 3 基于 Java 17、Spring Framework 6 与 Jakarta EE 9+,规范包名切换到 jakarta。Boot 3 的自动配置候选使用 AutoConfiguration.imports,持久化常见 Hibernate 6,安全进入 Security 6,可观测性主线转为 Micrometer Observation/Tracing,并强化 AOT 与 Native Image 支持。迁移不能只改 Boot 版本,必须整体校验 Servlet 容器、Cloud 发布列车、ORM、验证、Security、Agent 和公司 Starter。

追问: AutoConfiguration.imports 是 Boot 3 才出现的吗?

不是。Boot 2.7 已支持并推荐该方式;Boot 3 移除了通过旧 spring.factoriesEnableAutoConfiguration key 注册候选类的机制。

原理:Boot 3 自动配置内部链

2. 为什么 Boot 3 不能运行在 JDK 8 或 11

标准回答: Boot 3 基于 Spring Framework 6,框架最低基线就是 Java 17;框架 class 文件和所依赖 API 超出旧 JVM 能力。低版本 JVM 加载 Java 17 class 时会因 major version 不支持而抛出 UnsupportedClassVersionError,这属于运行时硬约束。

原理:编译、字节码和运行版本

3. 为什么 javax 改成 jakarta 不是批量替换 import 就够了

标准回答: JVM 使用完全限定类名识别类型,javax.servlet.Filterjakarta.servlet.Filter 是两个不同类型。第三方 Jar 的常量池、方法签名和注解仍可能引用旧类型,因此业务源码替换后仍会类缺失或签名不匹配。必须升级、替换或重新编译整个依赖链,同时更换为 Jakarta 兼容容器。

原理:Jakarta Web 请求链

4. Boot 3 自动配置为什么会生效

标准回答: @EnableAutoConfiguration 触发候选导入,Boot 从 AutoConfiguration.imports 读取自动配置类,执行排除、排序和条件评估。匹配的配置注册 BeanDefinition,之后仍由 Spring refresh() 主链执行 BeanFactory 后处理和 Bean 创建。排查时查看 Condition Evaluation Report,逐项确认 classpath、配置属性、Web 类型和已有 Bean。

原理:自动配置内部链

5. Boot 3 为什么强调 Observability

标准回答: Micrometer Observation 把一次业务操作抽象为统一观测上下文,可由 Handler 同时生成指标计时、Trace Span 和上下文传播。它统一埋点模型但不代替监控后端。生产中必须控制指标标签基数,订单号等高基数数据应放日志或 Trace 属性,而不是 Metrics Tag。

原理:Observability 调用链

6. AOT 与 Native Image 有什么区别

标准回答: AOT 是构建期分析和代码生成过程,Spring 会根据 BeanDefinition 生成初始化代码与 Runtime Hints;Native Image 是 GraalVM 的闭世界分析和本地可执行文件产物。AOT 也可以帮助 JVM 部署,但 Native 对反射、资源、动态代理更敏感。它通常改善启动和空闲内存,不保证峰值吞吐优于充分预热的 JVM。

原理:AOT 与 Native Image

7. 怎样把 Boot 2.7 安全迁移到 Boot 3

标准回答: 先把旧系统升级到最新可迁移的 2.7 基线并补齐测试;盘点依赖、Agent、JVM 参数和 Cloud 兼容矩阵;若条件允许先验证应用运行在 Java 17,再切换 Boot 3 和 Jakarta 依赖;回归 Security、Hibernate SQL、序列化、Filter、验证、Actuator 和 Trace;最后用压测、灰度和可回滚镜像逐步放量。不要同时升级框架、改业务和改数据库模型,否则失败时无法归因。

原理:迁移全过程

8. Java 17 的 Record 能否替代所有 DTO 和 Entity

标准回答: 不能。Record 适合由全部组件定义值语义的不可变载体,如 API DTO、查询投影和领域值对象;JPA Entity 通常需要代理、无参构造、可变状态和延迟加载,不适合机械替换。是否使用 Record 应由模型职责决定,而不是为了少写 getter。

原理:Record 的语义和边界

9. Java 17 有虚拟线程吗

标准回答: 没有正式虚拟线程。虚拟线程在 Java 21 正式发布,部分较新的 Boot 3.x 小版本提供集成配置。即使使用虚拟线程,数据库连接、下游配额、CPU 和锁仍是稀缺资源,必须继续做限流、超时和隔离。

原理:Java 21 版本边界

10. 升级后出现 NoSuchMethodError 怎么定位

标准回答: 这通常表示编译期和运行期看到的类版本不同。先保存完整调用栈,定位调用方和目标类,再用依赖树、effective POM 和类加载来源确认哪个 Jar 被 BOM 覆盖或重复引入。不要通过随机升降版本试错,因为即使错误暂时消失,也可能破坏另一组二进制兼容关系。

原理:Boot 3 故障取证

11. 编译 JDK、sourcetarget--release 和运行 JDK 有什么区别

标准回答: 编译 JDK 是实际执行 javac 的工具;source 约束语言语法,target 约束生成的 class 版本,但两者单独使用时不一定阻止代码误调用高版本标准库;--release 同时约束目标 class 版本和该版本可见的标准库 API;运行 JDK 是部署时真正加载 class 的 JVM。迁移时必须同时记录 IDE、Maven/Gradle、CI 镜像和生产容器中的真实 Java,不能只看 POM。

追问: 为什么本地能运行,容器里却报 major version 错误?

通常是构建使用 Java 17 生成 major version 61,而运行镜像仍是 Java 8,只能识别到 52。应检查最终镜像中的 java -version 和实际 class 版本,而不是重新打包碰运气。

原理:Java 17 最低基线与字节码

12. 所有 javax.* 包都要替换成 jakarta.*

标准回答: 不是。需要迁移的是 Jakarta EE 规范中的 Servlet、Validation、Persistence、Transaction 等包;Java SE 自带的 javax.cryptojavax.netjavax.sql 等不属于此次命名空间迁移,不能全局替换。正确做法是根据规范边界和编译错误逐项升级依赖。

原理:Jakarta 迁移边界

13. AutoConfiguration.imports 是 Spring Boot 3 才有的吗

标准回答: 不是。Boot 2.7 已支持并推荐 AutoConfiguration.imports,Boot 3 移除的是通过 spring.factoriesEnableAutoConfiguration key 注册自动配置候选类的旧方式。spring.factories 作为文件并未在所有扩展场景中消失,回答时必须限定为“自动配置候选注册机制”。

原理:自动配置注册的精确版本边界

14. Boot 3 中 @ConfigurationProperties 为什么常用 Record

标准回答: Record 天然适合不可变配置载体,组件由构造器一次性确定;Boot 3 对单个参数化构造器通常能推断构造器绑定,所以不必机械保留旧版类型级 @ConstructorBinding。但 Record 不是强制要求,复杂默认值、继承式模型或需要可变刷新的配置仍应按职责选择普通类。

追问: 配置中心动态刷新时不可变 Record 会自动变吗?

不会仅因它是 Record 就自动变化。是否重新绑定、重建 Bean 取决于 Spring Cloud 的刷新机制、Bean 作用域和配置组件实现,必须单独验证。

原理:Boot 3 配置绑定

15. Spring Security 5 升到 6 最容易漏什么

标准回答: 不能再照搬旧的 WebSecurityConfigurerAdapter 配置,通常改为声明 SecurityFilterChain;授权 DSL、RequestMatcher、方法安全配置以及部分默认行为也有变化。迁移不仅要验证登录成功,还要回归匿名访问、角色边界、CSRF、CORS、会话、JWT 失败响应和方法级授权,避免“接口能访问”掩盖越权。

原理:Spring Security 6 集成变化

16. 为什么升级到 Hibernate 6 后编译通过,SQL 仍可能出问题

标准回答: API 编译通过只证明类型可调用,不证明 HQL 解析、方言、类型映射、标识生成、分页、批处理和最终生成 SQL 与 Hibernate 5 相同。应保存关键 SQL、绑定参数和 EXPLAIN 基线,回归锁语义、时间类型、枚举、JSON、自定义 Dialect 及大批量操作。

原理:Hibernate 6 行为迁移

17. Boot 3 还必须使用 bootstrap.yml

标准回答: 不能脱离 Spring Cloud 和组件版本直接回答。Spring Boot 从 2.4 起引入 Config Data 机制,现代组件常通过 spring.config.import 在启动早期导入远程配置;某些旧版 Spring Cloud/Alibaba 项目仍依赖 bootstrap 上下文或兼容 Starter。迁移时要按精确依赖矩阵选择一种明确方式,并通过 Environment 属性来源和客户端日志证明远程配置何时被加载。

原理:Nacos Boot 2 与 Boot 3 配置导入边界

18. Boot 3 项目能随便搭配 Spring Cloud 和 Spring Cloud Alibaba 吗

标准回答: 不能。Boot、Spring Framework、Spring Cloud Release Train 和 Spring Cloud Alibaba 是多层兼容矩阵;只把 Boot 升到 3 可能导致自动配置、HTTP 客户端、负载均衡、注册配置客户端或 Jakarta 类型不兼容。应由兼容 BOM 管理版本,并检查 effective POM,避免手工覆盖核心依赖。

原理:微服务整体迁移

19. 内嵌 Tomcat 端口已监听,为什么还不能认为应用就绪

标准回答: 端口监听只证明 Web Server 已启动,不代表数据库迁移、缓存预热、Runner、消息订阅或外部依赖初始化已经完成。Liveness 表示进程是否需要重启,Readiness 表示是否应接收流量;两者混用会让未就绪实例接流量,或在下游故障时触发无意义重启风暴。

原理:从 main 到 Ready 的启动链

20. Boot 3 的优雅停机为什么只配 server.shutdown=graceful 还不够

标准回答: 完整停机要先让注册中心、Service 或负载均衡停止向实例分配新流量,等待摘流传播和连接排空,再让容器停止接新请求并在上限内完成存量请求。Kubernetes 的 preStop、Readiness、负载均衡传播时间和 terminationGracePeriodSeconds 必须覆盖这段窗口,否则进程仍会被 SIGKILL 强制结束。

原理:Boot 3 生产配置与停机链

21. Micrometer Observation、Metrics 和 Trace 是什么关系

标准回答: Observation 是一次操作的统一观测生命周期,具体 Handler 可以从它生成计时指标、Span 和上下文传播;Metrics 适合聚合趋势,Trace 适合还原单次跨服务链路,日志适合记录离散事件。Observation 不负责永久存储数据,仍需 Prometheus、OTLP Collector、Tempo/Jaeger 等后端。

追问: 为什么订单号不能作为 Metrics Tag?

订单号基数接近请求数,会产生海量时间序列,导致内存、查询和存储成本失控;它更适合日志字段或受控的 Trace 属性。

原理:Observability 内部链

22. 为什么 JVM 模式正常,Native Image 运行时却找不到类或资源

标准回答: JVM 可以在运行期动态扫描、反射和创建代理;Native Image 使用闭世界分析,构建期未发现且未通过 Runtime Hints 声明的反射成员、资源、序列化类型或代理接口可能不会进入产物。应根据失败路径补精确 Hint,并同时验证 JVM 和 Native 两种构建,不要通过“把所有类型都注册反射”掩盖边界。

原理:AOT 与 Native Image 内部原理

23. Boot 3.x 是否代表所有 3.x 小版本能力都一样

标准回答: 不一样。Boot 3.0、3.1、3.2 及后续小版本会升级 Java 支持范围、Servlet 容器、Spring Framework、依赖 BOM、Observability、HTTP 客户端和虚拟线程集成。设计和排查时必须写出精确版本,查对应系统要求及依赖清单,不能把某个后续小版本能力倒推成整个 3.x 都支持。

原理:双轨版本与精确版本原则

24. Java 17 和 Java 21 的能力边界怎样回答

标准回答: Java 17 是 Boot 3 的最低现代基线,并正式包含 Record、密封类、文本块、instanceof 模式匹配等能力;虚拟线程在 Java 21 正式发布。项目运行 Java 17 时不能使用 Java 21 API;运行 Java 21 也不代表所有依赖和 Boot 小版本自动支持虚拟线程集成。

原理:Java 21 版本边界

25. Boot 2 和 Boot 3 微服务能否在迁移期共存

标准回答: 可以,只要跨服务契约保持兼容。HTTP/JSON、消息格式、数据库协议并不要求两端使用相同 Boot 版本;但要重点验证序列化、日期格式、错误响应、Trace 传播头、注册元数据、认证 Token 和消息 Schema。正确迁移方式是契约测试、消费者驱动兼容、灰度和可回滚,而不是要求整个系统同一晚升级。

原理:微服务分批升级边界

26. 怎样证明 Boot 3 迁移真正成功,而不只是“启动成功”

标准回答: 至少要验证编译和运行 JDK、依赖树、启动条件报告、核心 API 契约、Security 权限、数据库 SQL 与执行计划、消息消费、配置刷新、Trace/Metrics、资源基线、优雅停机、滚动发布和回滚。还要保存升级前后性能与错误率基线,并在灰度期观察,而不是只看端口和健康检查返回 200。

原理:商业系统迁移验收

27. Boot 3 自动配置不生效时从哪里开始排查

标准回答: 开启 --debug 或读取 Condition Evaluation Report,先确认候选自动配置是否被导入,再逐项查看 @ConditionalOnClass、属性条件、Web 应用类型、已有 BeanDefinition 和排除配置。若类根本不在候选列表,检查 AutoConfiguration.imports 打包路径;若候选存在但未匹配,应根据报告修复条件,而不是重复添加 @ComponentScan

原理:自动配置条件执行链

28. Boot 3 的 Actuator 端点能直接全部暴露公网吗

标准回答: 不能。envconfigprops、heap dump、thread dump、日志级别等端点可能暴露配置、路径、内部结构和敏感数据;生产应采用最小暴露、独立管理网络、认证授权和审计。健康端点也要控制详情展示,探针只返回调度所需状态。

原理:Boot 3 生产配置与端点边界