Spring 综合真题解析
真实面试题完整回答 + 原理串联演示
一、IoC 容器
真题 1:Spring 为什么要用三级缓存而不是二级?
面试官意图:考察对循环依赖和 AOP 代理机制的深度理解
完整回答:
三级缓存的核心优势是延迟代理创建。
二级缓存的方案是这样的:实例化 Bean 后,不管有没有循环依赖,都必须立即决定是否创建 AOP 代理,然后把代理对象放入二级缓存。这样即使没有循环依赖,所有 Bean 也会在实例化后就被迫创建代理。
三级缓存用
ObjectFactory做了一层延迟——只有真的发生循环依赖、需要提前暴露时,才调用工厂方法创建代理。没有循环依赖的 Bean 走正常流程:postProcessAfterInitialization阶段才生成代理。所以本质问题是:二级缓存无法区分"这个 Bean 有没有被循环依赖引用"。三级缓存通过 ObjectFactory 的延迟执行做到了区隔。
原理串联: **三级缓存原理** → **Bean生命周期(后置处理阶段)** → **AOP代理生成**
真题 2:Spring 如何推断使用哪个构造方法实例化 Bean?
面试官意图:考察对 Bean 实例化源码的了解
完整回答:
Spring 的构造器推断逻辑:
- 如果 Bean 只有一个构造方法——无论是否有参——直接使用它(从 Spring 4.3 开始,唯一构造方法无需 @Autowired)
- 如果有多个构造方法:
- 找标注了 @Autowired 的构造方法,有且唯一则使用
- 有多个 @Autowired 构造方法则抛异常
- 没有 @Autowired 时,找默认无参构造方法
- 没有默认无参构造方法则抛异常
选择好构造方法后,Spring 根据构造参数类型在容器中查找依赖 Bean,进行构造器注入。
原理串联: **refresh()启动流程(第11步)** → **依赖注入**
二、AOP
真题 3:@Configuration 加 final 会怎样?为什么?
面试官意图:考察对 CGLIB 增强和 Full/Lite 模式的理解
完整回答:
@Configuration类默认是 Full 模式——被 CGLIB 创建子类代理。CGLIB 代理拦截 @Bean 方法,在方法调用时检查容器中是否已有该 Bean,有则返回容器中的单例,无则创建。如果
@Configuration类加了final,CGLIB 无法生成子类(final 类不能被继承),自动降级为 Lite 模式。此时 @Bean 方法就是普通方法调用,方法间调用不再保证单例。比如:
java@Configuration public final class AppConfig { // 降级为 Lite @Bean public A a() { return new A(b()); } // b() 每次返回新实例 @Bean public B b() { return new B(); } }
原理串联: **@Configuration增强** → **CGLIB代理原理**
三、事务管理
真题 4:REQUIRES_NEW 在同一个事务管理器下真的会新建物理连接吗?
面试官意图:考察对事务传播行为源码级的理解
完整回答:
会新建物理连接。
DataSourceTransactionManager的handleExistingTransaction()处理 REQUIRES_NEW 时:
- suspend():从当前线程解绑旧的 ConnectionHolder,保存同步器列表、事务名称/只读/隔离级别到 SuspendedResourcesHolder
- doBegin():从连接池获取新的 Connection,setAutoCommit(false),绑定到当前线程
- 新事务在新连接上执行
- 执行完毕后,commit 新连接,归还到连接池
- resume():恢复被挂起的旧事务状态,重新绑定旧连接到线程
如果连接池只有一个连接,REQUIRES_NEW 会阻塞等待旧事务释放连接。
原理串联: **传播行为与隔离级别** → **DataSourceTransactionManager源码**
真题 5:Spring 事务默认回滚什么异常?会回滚 checked exception 吗?
面试官意图:考察对回滚规则机制的源码理解
完整回答:
默认只回滚 RuntimeException 和 Error,checked exception(如 IOException、SQLException)不会触发回滚。
判断逻辑在
RuleBasedTransactionAttribute.rollbackOn():
- 如果指定了 rollbackFor/noRollbackFor 规则,按规则匹配
- 没有规则时,调用
DefaultTransactionAttribute.rollbackOn():return (ex instanceof RuntimeException || ex instanceof Error)所以如果要回滚 checked exception,必须显式:
@Transactional(rollbackFor = Exception.class)
原理串联: **事务高级特性(回滚规则)** → **TransactionInterceptor源码**
四、Spring Boot
真题 6:Spring Boot 和普通 Spring 启动流程的差异在哪?
面试官意图:考察对 Spring Boot 自动配置和容器启动的理解
完整回答:
Spring Boot 在
SpringApplication.run()中多做了:
- 推断 Web 应用类型(Reactive/Servlet/None)
- 加载 ApplicationContextInitializer(META-INF/spring.factories)
- 加载 ApplicationListener
- 自动装配:@EnableAutoConfiguration -> 加载 AutoConfiguration.imports -> 条件评估
- 内嵌 Web 服务器启动:onRefresh() 模板方法中启动 Tomcat/Jetty/Undertow
但核心的
refresh()方法流程与普通 Spring 完全一致——ConfigurableApplicationContext.refresh() 这 12 步是相同的。
原理串联: **自动配置原理** → **refresh()启动流程**
真题 7:你自己写过 Starter 吗?具体步骤?
面试官意图:考察对自动配置机制的实战能力
完整回答:
创建自定义 Starter 的 4 个步骤:
- 自动配置类:@Configuration + @ConditionalOnClass/@ConditionalOnMissingBean
- 属性类:@ConfigurationProperties(prefix = "xxx")
- 注册文件:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(Spring Boot 2.7+)
- 依赖管理:spring-boot-autoconfigure-processor 编译依赖
命名规范:官方用
spring-boot-starter-{name},三方用{name}-spring-boot-starter。
原理串联: **条件注解与定制Starter** → **自动配置原理**
五、Spring MVC + Security
真题 8:无状态 JWT 方案怎么处理 token 续期?怎么让 token 及时失效?
面试官意图:考察 JWT 无状态认证的工程实践
完整回答:
续期方案:
- Refresh Token 模式:短期 Access Token(15-30min)+ 长期 Refresh Token(7-30天)
- 滑动过期:每次请求检查剩余时间,小于阈值时重新签发
及时失效方案:
- 黑名单:Redis 维护登出 Token 黑名单,TTL 设为 Token 剩余有效期
- 短有效期 + 频繁刷新:Access Token 5-15 分钟,配合 Refresh Token
- 版本号:用户密码变更时递增,Token 携带版本号,服务端校验
原理串联: **JWT与OAuth2** → **认证流程**
六、Spring Cloud
真题 9:微服务架构下如何实现分布式事务?
面试官意图:考察分布式事务方案选型
完整回答:
Seata 提供了三种模式:
AT 模式(推荐优先):自动解析 SQL 生成 UNDO_LOG 回滚日志。两阶段提交——第一阶段执行 SQL + 记录回滚日志,第二阶段提交/根据 UNDO_LOG 回滚。对业务代码无侵入。
TCC 模式:手动实现 Try(预留资源)/Confirm(确认)/Cancel(补偿)。性能更高但侵入性强。
Saga 模式:适用于长业务流程,通过编排或 choreography 实现补偿操作。
选型建议:简单 CRUD 用 AT,高并发用 TCC,长流程用 Saga。
原理串联: **分布式事务** → **本地事务基础**
📚 相关链接
- **面试高频100题** — 分板块面试题库
- **面试知识体系总览** — 知识地图总览
- ← 返回 **面试知识体系总览**