一、面试题分类导图

二、20 道高频题(源码级答案)
IoC 容器
| # | 问题 | 源码定位 | 一句话答案 |
|---|---|---|---|
| 1 | BeanFactory 与 ApplicationContext 区别? |
AbstractApplicationContext.refresh / preInstantiateSingletons |
后者继承前者并多企业级能力(事件/国际化/资源),且默认饿加载单例 |
| 2 | refresh() 有哪些关键步骤? |
AbstractApplicationContext.refresh |
12 步:准备→刷新工厂→BFPP→BPP→消息源→多播器→onRefresh→注册监听器→完成BeanFactory初始化→finishRefresh 等 |
| 3 | getBean 到对象创建全链路? |
doGetBean → getSingleton → createBean → doCreateBean |
查缓存→创建→实例化→提前暴露→填充→初始化→AOP代理 |
| 4 | 为什么用三级缓存解决循环依赖? | DefaultSingletonBeanRegistry(singletonFactories/earlySingletonObjects/singletonObjects) |
三级用 ObjectFactory 延迟生成早期引用,既解决循环又避免提前 AOP 代理 |
| 5 | 构造器循环依赖能解决吗? | doCreateBean 前需先实例化 |
不能,实例化即需依赖,无早期引用可暴露,直接抛 BeanCurrentlyInCreationException |
Bean 生命周期
| # | 问题 | 源码定位 | 一句话答案 |
|---|---|---|---|
| 6 | Bean 生命周期有哪些阶段? | initializeBean / invokeAwareMethods |
实例化→提前暴露→填充→Aware→@PostConstruct→InitializingBean→init-method→AOP→销毁 |
| 7 | ApplicationContextAware 在哪注入? |
ApplicationContextAwareProcessor(BPP) |
它不在 invokeAwareMethods,由 ApplicationContextAwareProcessor.postProcessBeforeInitialization 注入 |
| 8 | @Autowired 何时注入? |
AutowiredAnnotationBeanPostProcessor.postProcessProperties |
在 populateBean 阶段,经 resolveDependency → getBean 递归 |
| 9 | BeanPostProcessor 与 BeanFactoryPostProcessor 区别? |
第 5 步 vs initializeBean |
BFPP 改 BD(实例化前),BPP 加工实例(实例化后) |
AOP
| # | 问题 | 源码定位 | 一句话答案 |
|---|---|---|---|
| 10 | @EnableAspectJAutoProxy 注册了什么? |
AspectJAutoProxyRegistrar |
注册 AnnotationAwareAspectJAutoProxyCreator(BPP) |
| 11 | 代理何时创建? | wrapIfNecessary |
postProcessAfterInitialization(初始化后),故填充阶段注入的是原始 Bean |
| 12 | JDK 还是 CGLIB 怎么选? | DefaultAopProxyFactory.createAopProxy |
proxyTargetClass=true/无接口→CGLIB;否则有接口→JDK |
| 13 | 责任链怎么执行? | ReflectiveMethodInvocation.proceed |
递归推进 MethodInterceptor,每个调 proceed() 进入下一个 |
| 14 | 同类自调用 AOP 为何失效? | this 指向原始对象 |
代理是包装非替换,自调用绕过代理 |
MVC
| # | 问题 | 源码定位 | 一句话答案 |
|---|---|---|---|
| 15 | DispatcherServlet 九大组件? |
initStrategies |
含 HandlerMapping/HandlerAdapter/ViewResolver 等,启动时初始化一次 |
| 16 | doDispatch 流程? |
DispatcherServlet.doDispatch |
getHandler→getHandlerAdapter→preHandle→handle→postHandle→processDispatchResult |
| 17 | @RequestBody 怎么解析? |
RequestResponseBodyMethodProcessor + HttpMessageConverter |
经 HttpMessageConverter 反序列化请求体 |
| 18 | 拦截器三方法时机? | HandlerExecutionChain |
preHandle 正序、postHandle/afterCompletion 倒序;异常时 postHandle 不执行 |
Boot / 事务
| # | 问题 | 源码定位 | 一句话答案 |
|---|---|---|---|
| 19 | 自动配置原理? | AutoConfigurationImportSelector |
读 imports/spring.factories→排序→按 @Conditional 过滤→延迟导入保证用户 Bean 优先 |
| 20 | @Transactional 为何失效? |
TransactionInterceptor |
自调用/非public/异常被吞/checked异常/引擎不支持/传播行为不当/多线程 七类 |
三、记忆要点
📌 三条主线:
- 容器主线 :
refresh十二步是总纲,所有 BFPP/BPP/AOP 都挂在上面。- 代理主线:AOP = BPP 在初始化后包代理;事务 = 特殊的 AOP Advisor。
- 请求主线 :
DispatcherServlet.doDispatch串联九大组件。
四、常见误区
| 误区 | 正解 |
|---|---|
| 面试题只要背结论 | 源码定位才是区分度,要能说出「在哪个类哪个方法」 |
| AOP 和事务是两套机制 | 事务本质是 AOP 的 TransactionInterceptor |
| 自动配置无条件全生效 | 按 @Conditional 过滤 |
| 循环依赖二级缓存够用 | 需三级以支持延迟 AOP 代理 |
🧪 自测建议
把上表 20 题遮住「答案列」自问自答;卡壳的回到对应篇重读。能流畅说出 18/20 即达面试安全线。
下一篇预告
第 30 篇(收尾):手写 Mini-Spring------用不到 300 行代码实现最简 IoC + DI,把前面学的 BeanFactory、BeanPostProcessor、依赖注入、循环依赖串成一次「从理论到动手」的闭环。
如果这篇对你有帮助,欢迎 点赞 · 收藏 · 关注 三连支持。
Spring 源码系列共 30 篇,由浅入深持续更新中。有疑问或想深挖的源码点,评论区告诉我,下篇见。