主题
面试题蒸馏卡:Spring 框架
从
语雀-Java开发/Spring全家桶58 篇提炼的高频面试题。每题按「标准答 → 追问链 → 常见误解」组织。详细机制见对应概念卡。
Q1:说说 Spring 的 IoC 和 DI?
标准答:IoC(控制反转)是把「创建对象、管理依赖」的控制权从程序反转到容器的思想,DI(依赖注入)是它的实现。Spring 容器创建 Bean 后自动注入依赖,调用者无需 new、无需主动获取,实现松耦合。DI 有三种方式:setter 注入、构造器注入、字段注入,官方推荐构造器注入。
追问链:
- "IoC 和 DI 是一回事吗?" → IoC 是思想,DI 是实现;还有 Service Locator 等其它实现
- "三种注入方式区别?" → setter 先无参构造再注入(依赖可缺)、构造器创建即注入(依赖必需)、字段注入反射赋值(最简洁但难测试)
- "为什么推荐构造器注入?" → 依赖强制必需、字段可 final 不可变、易做单元测试
常见误解:❌ 把 IoC 和 DI 混为一谈;❌ 以为字段注入最方便就该多用。
Q2:@SpringBootApplication 的原理?
标准答:它是复合注解,核心三件——@SpringBootConfiguration(=@Configuration)+ @ComponentScan(扫自己包)+ @EnableAutoConfiguration(自动装配)。自动装配靠 @Import(AutoConfigurationImportSelector) 从 classpath 的 META-INF/spring.factories(Boot 2.7 起改为 AutoConfiguration.imports)加载配置类,经去重、排除、条件过滤后注册进容器。
追问链:
- "@ComponentScan 和 @EnableAutoConfiguration 区别?" → 前者扫自己包的 @Component,后者装配第三方 jar 的配置类
- "自动装配条件过滤是什么?" → @ConditionalOnClass/@ConditionalOnBean/@ConditionalOnMissingBean
- "starter 和自动装配什么关系?" → starter = 依赖聚合 + 自动配置类,光引依赖没配置类不会自动装配
常见误解:❌ 以为自动装配就是 @ComponentScan;❌ 以为 spring.factories 永远有效(2.7 后改了)。
Q3:SpringMVC 的执行流程?
标准答:请求 → DispatcherServlet → HandlerMapping 找 Handler+拦截器(HandlerExecutionChain)→ HandlerAdapter 执行 → 返回 ModelAndView → ViewResolver 解析 → 渲染。拦截器三段:preHandle(正向)→ postHandle(逆向)→ afterCompletion(逆向)。
追问链:
- "DispatcherServlet 九大组件?" → HandlerMapping/HandlerAdapter/ViewResolver 是核心三件,还有 Multipart/Locale/Theme/Exception 等
- "拦截器三个回调时机?" → preHandle 在 Handler 前、postHandle 在 Handler 后视图前、afterCompletion 在视图后(总会执行)
- "参数绑定做了什么?" → 类型转换、格式化、校验、HttpMessageConverter(JSON↔对象)
常见误解:❌ 以为请求直接找 Controller;❌ 以为 postHandle 一定执行(preHandle 返回 false 时不执行)。
Q4:Spring 事务为什么失效?
标准答:@Transactional 基于 AOP 动态代理,失效都是因为「没走代理」或「异常不满足回滚规则」:
- 同类自调用(绕过代理)
- 非 public 方法
- 异常被 catch 吞掉
- Checked 异常(默认只回滚 RuntimeException/Error)
- 数据库引擎不支持事务(MyISAM)
追问链:
- "自调用怎么解决?" → 拆到不同 Bean,或注入自身代理/AopContext
- "默认什么异常回滚?" → RuntimeException + Error;Checked 需 rollbackFor
- "异常吞掉怎么补救?" → 手动 setRollbackOnly()
常见误解:❌ 以为加了注解就一定生效;❌ 以为抛异常就回滚(Checked 不回滚)。
Q5:@Autowired 和 @Resource 区别?
标准答:@Autowired 是 Spring 的,**按类型(byType)**注入,多个同类型再按名称 + @Qualifier;@Resource 是 JSR-250 标准,**按名称(byName)**优先,找不到再 byType。
追问链:
- "接口有多个实现怎么注入?" → @Autowired 配 @Qualifier 指定,或 @Resource(name=...)
- "required 属性?" → @Autowired(required=false) 可允许为空
常见误解:❌ 以为 @Autowired 按名称注入。
Q6:Bean 的生命周期和循环依赖?
标准答(衔接 [Spring IOC容器初始化与循环依赖](./Spring IOC容器初始化与循环依赖)):Bean 生命周期 = 实例化 → 属性填充 → 初始化(Aware/BeanPostProcessor)→ 使用 → 销毁。循环依赖靠三级缓存解决:singletonObjects(成品)、earlySingletonObjects(提前暴露)、singletonFactories(三级,存 ObjectFactory),A/B 相互依赖时通过提前暴露半成品 + 代理解决。
追问链:
- "为什么需要三级缓存?" → 二级缓存解决不了 AOP 代理场景,三级存工厂延迟生成代理
- "构造器循环依赖能解决吗?" → 不能,必须用 @Lazy 或重构
常见误解:❌ 以为构造器注入的循环依赖也能靠三级缓存解决(只能解决 setter/字段注入的)。
关联
- 总览:Spring技术栈总览
- 已有底子:[Spring IOC容器初始化与循环依赖](./Spring IOC容器初始化与循环依赖) · [Spring AOP与声明式事务](./Spring AOP与声明式事务)
- 域地图:A00-百科/Java后端/Java后端