我们循序渐进完整走完:IOC 容器 → Bean 生命周期 → 循环依赖 → AOP → 事务 → SpringMVC 全流程 → SpringBoot 自动配置 → 资源与环境配置 → 事件驱动 → 类型转换与参数校验 → 全套扩展点
从注解使用,到底层源码执行链路;从只会写业务,到能断点跟源码、懂底层原理、解线上 BUG。这一篇,做最终闭环收拢,干净收尾。
一、两大核心全链路 极简复盘
1. Spring IOC 容器启动流程
- 容器刷新
refresh() - 扫描解析,全部资源转为
BeanDefinition - 执行
BeanDefinitionRegistryPostProcessor动态注册 Bean - 执行
BeanFactoryPostProcessor修改 Bean 定义 - 开始创建单例 Bean:构造器实例化 → 依赖注入(属性填充)
BeanPostProcessor前置处理(postProcessBeforeInitialization)- 执行初始化:
@PostConstruct→InitializingBean.afterPropertiesSet()→ 自定义init-method BeanPostProcessor后置处理(postProcessAfterInitialization,AOP 代理生成时机)- 完整 Bean 存入单例池,容器刷新完成
核心口诀:先定义、后实例;先填充依赖,后前置处理;再初始化,最后后置处理并生成代理。
2. SpringMVC 请求执行全流程
- Tomcat 接收请求,委派
DispatcherServlet - 核心方法
doDispatch统一调度 HandlerMapping根据 URL 匹配 Controller 方法HandlerAdapter适配当前处理器- 拦截器
preHandle按配置顺序执行 - 适配器内部:参数解析 →
InvocableHandlerMethod.doInvoke反射执行 Controller - 处理器处理返回值、统一封装响应
- 拦截器
postHandle按配置顺序的逆序执行 - 视图渲染(非 JSON 场景)
- 若
preHandle返回 true,触发afterCompletion逆向执行,进行资源清理
二、高频经典深坑
1. 循环依赖
- Spring 仅支持:setter / 字段注入、单例 Bean
- 不完全支持:构造器注入、多例 Bean、静态 Bean;代理 Bean 循环依赖部分支持,取决于代理创建方式
- 核心解决方案:三级缓存 + 提前暴露半成品 Bean
2. AOP 失效核心原因
- 同类中
this.方法()内部调用,不走代理(可通过AopContext.currentProxy()或自注入解决) - 非 public / private / final / static 方法
- 对象手动
new,不受 Spring 容器管理 - 未开启动态代理、注解未扫描到
3. 事务失效核心原因
- 底层基于 AOP 代理,不走代理调用就没有事务
- 非 public 方法、同类内部调用
- 异常被
try-catch捕获,事务框架感知不到异常,无法触发回滚 - 传播行为配置错误、数据库引擎不支持事务
4. 配置与 Environment
- 所有配置最终都被封装为
PropertySource - 读取配置时从上到下遍历,后加入的配置优先级更高
- SpringBoot 配置优先级:命令行 > 系统属性 > 环境变量 > 配置文件
- 所有配置最终被封装为
PropertySource,后加入的PropertySource优先级更高 - Spring Boot 完整配置优先级(从高到低):
- 命令行参数
- Java 系统属性
- 操作系统环境变量
application-{profile}.properties/ymlapplication.properties/yml@PropertySource加载的配置
5. 注解注入与参数绑定
@Value、@Autowired由AutowiredAnnotationBeanPostProcessor处理,在属性填充阶段完成注入;@PostConstruct由CommonAnnotationBeanPostProcessor处理,在初始化前置阶段执行- MVC 参数绑定 = 参数解析器 + 类型转换体系共同完成
@Valid参数校验,依托统一Validator校验器
三、Spring 核心扩展点 汇总
按执行时机 & 用途精简总结:
| 扩展点 | 执行时机 | 核心用途 |
|---|---|---|
BeanDefinitionRegistryPostProcessor |
容器早期执行 | 可动态新增 Bean 定义(ConfigurationClassPostProcessor 实现了此接口,完成配置类解析、扫描、@Import 等核心逻辑) |
BeanFactoryPostProcessor |
Bean 定义加载完成后执行 | 可修改已有 Bean 定义 |
BeanPostProcessor |
Bean 初始化前后全局拦截增强 | AOP 代理生成的核心依靠它(AbstractAutoProxyCreator);依赖注入也在其扩展接口 InstantiationAwareBeanPostProcessor 的支持下完成 |
InitializingBean / DisposableBean |
单个 Bean 初始化/销毁时 | 自定义初始化、资源销毁回调 |
FactoryBean |
Bean 创建时 | 用于构建复杂、重型组装类 Bean,隐藏创建复杂逻辑。典型场景:整合 MyBatis 时创建 Mapper 代理对象、创建有复杂初始化逻辑的第三方 Bean |
ImportSelector |
配置类处理时立即执行 | 批量导入配置类 |
DeferredImportSelector(ImportSelector 子接口) |
延迟到所有配置类处理完毕后执行 | SpringBoot 自动配置核心(AutoConfigurationImportSelector 实现了 DeferredImportSelector) |
ImportBeanDefinitionRegistrar |
配置类处理时 | 手动编码注册 Bean,各种 @Enable 开关注解底层实现 |
ApplicationEvent 事件体系 |
运行时 | 发布订阅模式,业务解耦、框架内部解耦利器 |
SmartInitializingSingleton |
在所有单例 Bean 都实例化完成后触发 | 用于执行容器启动完成后的全局回调逻辑,如预加载缓存、校验配置等 |
四、30 道 Spring 源码高频面试题
一、IOC & Bean 核心(1~8)
1. 什么是 IOC 控制反转、DI 依赖注入?
- IOC:控制权反转,将对象创建、管理、依赖维护的权利,从开发者交给 Spring 容器。
- DI:依赖注入,容器自动解析 Bean 之间的依赖,自动赋值,解耦代码。
- 核心价值:降耦合、易扩展、便于统一管理 Bean 生命周期。
2. 简述 Spring Bean 完整生命周期?
BeanDefinition 加载 → 构造器实例化 → 依赖属性填充 → BeanPostProcessor 前置处理 → @PostConstruct → InitializingBean → 自定义 init 方法 → BeanPostProcessor 后置处理(生成代理) → 放入单例池 → 容器关闭执行销毁方法。
3. 三级缓存分别是什么?作用?
- 一级缓存 :
singletonObjects完整成熟 Bean - 二级缓存 :
earlySingletonObjects半成品 Bean(已实例化未注入) - 三级缓存 :
singletonFactoriesLambda 工厂,提前暴露 Bean 引用
核心:通过三级缓存提前暴露引用,解决单例 Setter / 字段循环依赖。
4. 为什么不用二级缓存?构造器注入循环依赖为什么无解?
- 二级缓存无法解决「循环依赖 + AOP 代理」场景;
- 构造器注入:实例化就要依赖对象,没有半成品阶段,无法提前暴露,直接报错。
5. BeanFactory 和 ApplicationContext 区别?
- BeanFactory:最顶层容器接口,懒加载、只负责 Bean 获取
- ApplicationContext:继承 BeanFactory,具备国际化、事件发布、资源加载、自动扫描、完整生命周期管理。
6. Spring 单例 Bean 是线程安全的吗?
不安全。Spring 单例只保证容器中只有一份对象,不保证线程安全;不要在单例 Bean 中定义可变成员变量。
7. @Configuration、@Bean 底层原理?
配置类会被 ConfigurationClassPostProcessor 解析,Full 模式下配置类会被 CGLIB 代理,保证 @Bean 方法返回单例 Bean。
8. 原型 Bean 会被完整管理吗?
不会。多例 Bean 容器只负责创建,不会统一销毁,DisposableBean 不会执行。
二、AOP & 事务(9~15)
9. JDK 动态代理 和 CGLIB 代理区别
- JDK 代理:基于接口,只能代理接口实现类
- CGLIB 代理:基于子类继承,无需接口,可代理普通类
- Spring 默认:有接口用 JDK,无接口用 CGLIB。
10. AOP 五种通知顺序?
前置通知 → 环绕前置 → 目标方法 → 环绕后置 → 后置通知 → 异常通知 → 最终通知。
11. 为什么 this 内部调用导致 AOP 失效?
this 是原生对象,不是 Spring 代理对象;AOP 增强全部在代理类中,原生调用不会走增强逻辑。解决:内部注入自身、通过代理对象调用。
12. Spring 事务底层原理?
基于 AOP 动态代理拦截目标方法;事务开启时,将数据库 Connection 绑定到当前线程;异常触发回滚,正常执行提交。
13. 事务传播行为核心区别
- REQUIRED:有事务加入,无则新建
- REQUIRES_NEW:无论有无,都新建独立事务
- NESTED:嵌套事务,依赖父事务保存点,父回滚子全部回滚
14. 常见事务失效场景
非 public 方法、this 内部调用、异常被 try-catch 吃掉、传播行为配置错误、没有被 Spring 代理、引擎不支持事务。
15. 事务隔离级别
读未提交、读已提交、可重复读、串行化;Spring 可全局 / 方法级单独指定,解决脏读、不可重复读、幻读。
三、SpringMVC 核心(16~21)
16. DispatcherServlet 作用
SpringMVC 核心总调度器,接收所有请求,统一分发、匹配处理器、执行适配器、视图解析、统一响应。
17. HandlerMapping 和 HandlerAdapter 区别
- HandlerMapping:根据 URL 查找 Controller 处理器
- HandlerAdapter:适配不同处理器,执行目标方法
18. Controller 方法如何被执行?
adapter.handle() → 解析参数 → 调用 InvocableHandlerMethod.invokeForRequest → 最终执行 doInvoke → 反射执行目标 Controller 方法。
19. SpringMVC 参数绑定原理
请求原始字符串 → 参数解析器获取参数 → 调用 ConversionService、Formatter 做类型转换 → 绑定到 Controller 方法入参。
20. 拦截器 和 Filter 区别
- Filter:Servlet 原生,在最外层,控制所有请求
- Interceptor:Spring 层级,在 Controller 前后,可使用 Spring 容器 Bean
21. @ResponseBody 实现原理
由 RequestResponseBodyMethodProcessor 处理,通过消息转换器(Jackson)将对象序列化为 JSON 直接写入响应流。
四、SpringBoot 自动配置 & 配置体系(22~26)
22. @SpringBootApplication 三大组成
@ComponentScan:包扫描@SpringBootConfiguration:标记为配置类@EnableAutoConfiguration:开启自动配置
23. 自动配置底层原理
@Import 导入 AutoConfigurationImportSelector,SPI 读取全部自动配置类,通过 @Conditional 条件注解按需加载。
24. spring.factories 与 imports 区别
- SpringBoot 2.7 之前 :使用
spring.factories - 2.7 之后 :废弃工厂文件,使用
AutoConfiguration.imports轻量化配置
25. @Conditional 系列注解作用
条件装配,满足类存在、Bean 存在、配置属性存在等条件,自动配置类才会生效,实现按需装配。
26. Spring 配置加载优先级(从高到低)
- 命令行参数
- 系统属性
- 系统环境变量
- 外部配置文件
- 项目内部
yml/properties - 框架默认配置
五、扩展点 & 事件 & 综合(27~30)
27. BeanFactoryPostProcessor 和 BeanPostProcessor 区别
- BeanFactoryPostProcessor :Bean 创建之前,修改
BeanDefinition - BeanPostProcessor:Bean 创建之后,对 Bean 实例增强、代理、注入
28. ImportSelector 与 ImportBeanDefinitionRegistrar
- ImportSelector:批量导入配置类,自动配置核心
- ImportBeanDefinitionRegistrar :手动编码注册
BeanDefinition,用于中间件接口扫描
29. Spring 事件驱动原理
基于发布订阅模式,ApplicationEventPublisher 发布事件,ApplicationListener 或 @EventListener 监听消费;支持同步、异步、事务绑定事件,实现业务解耦。
30. 你用过哪些 Spring 扩展点?
实际常用:BeanPostProcessor、WebMvcConfigurer、HandlerInterceptor、@EventListener、FactoryBean、Import 扩展,用来做统一增强、自定义配置、中间件整合、业务解耦。