复习定位
Spring 面试核心不是注解背诵,而是理解容器如何管理对象、代理如何增强方法、事务为什么有时会失效,以及 Spring Boot 如何把配置自动装起来。
IoC 和 DI
IoC 是控制反转:对象的创建和依赖关系不再由业务代码自己 new,而是交给 Spring 容器管理。
DI 是依赖注入:容器把一个对象依赖的其他对象注入进来,常见方式有构造器注入、setter 注入、字段注入。
更推荐构造器注入,因为依赖明确、方便测试,也能配合 final 避免对象半初始化。
Bean 生命周期
常见链路:
- 实例化 Bean。
- 填充属性。
- 执行 Aware 回调。
- BeanPostProcessor 前置处理。
- 初始化方法,例如
@PostConstruct、InitializingBean、init-method。 - BeanPostProcessor 后置处理。
- Bean 可用。
- 容器关闭时执行销毁逻辑。
AOP 代理通常在后置处理阶段生成,所以你拿到的 Bean 可能已经不是原始对象,而是代理对象。
AOP
AOP 用来把日志、权限、事务、监控这类横切逻辑从业务代码里抽出去。
关键词:
- Join Point:可被增强的位置。
- Pointcut:匹配哪些位置。
- Advice:增强逻辑。
- Aspect:切面,包含切点和通知。
- Proxy:代理对象。
Spring AOP 通常基于代理。如果目标类实现了接口,可以用 JDK 动态代理;否则常见是 CGLIB 生成子类代理。
面试重点:Spring AOP 只对经过 Spring 容器代理对象的方法调用生效,自调用通常不会触发切面。
Spring 事务
声明式事务一般通过 @Transactional 实现,本质也是 AOP。
事务传播行为
高频只要先掌握:
- REQUIRED:有事务就加入,没有就新建,默认值。
- REQUIRES_NEW:总是开启新事务,外层事务会挂起。
- NESTED:嵌套事务,依赖保存点。
- SUPPORTS:有事务就加入,没有就非事务执行。
- NOT_SUPPORTED:以非事务执行。
- MANDATORY:必须有事务,否则报错。
- NEVER:必须没有事务,否则报错。
事务失效场景
常见原因:
- 方法不是 public。
- 类没有交给 Spring 管理。
- 同类内部方法自调用。
- 异常被捕获后没有继续抛出。
- 默认只回滚运行时异常,受检异常需要配置
rollbackFor。 - 数据库或存储引擎本身不支持事务。
一句话回答:声明式事务靠代理,绕过代理就容易失效。
Spring MVC 请求流程
大致流程:
- 请求进入 DispatcherServlet。
- HandlerMapping 找到处理器。
- HandlerAdapter 调用 Controller。
- 参数绑定和校验。
- 执行业务逻辑。
- 返回 ModelAndView 或响应体。
- 视图解析或消息转换。
- 返回响应。
REST 场景里更常见的是通过 HttpMessageConverter 把对象转成 JSON。
Spring Boot 自动配置
Spring Boot 的价值是约定大于配置。它会根据类路径、配置项、条件注解自动创建一批 Bean。
常见条件注解:
@ConditionalOnClass:类路径存在某个类才生效。@ConditionalOnMissingBean:容器里没有某个 Bean 才创建默认 Bean。@ConditionalOnProperty:配置项满足条件才生效。
回答自动配置时可以抓住三句话:
- 启动类触发自动配置导入。
- 自动配置类通过条件注解决定是否生效。
- 用户自定义 Bean 通常可以覆盖默认配置。
循环依赖
Spring 可以解决一部分单例 Bean 的 setter 循环依赖,核心依赖三级缓存提前暴露对象引用。
但构造器循环依赖解决不了,因为对象还没构造完成,无法提前暴露。原型 Bean 循环依赖也不适合靠缓存解决。
面试收束
Spring 八股回答要围绕“容器 + 代理”。IoC 管对象,AOP 管增强,事务靠代理,自动配置靠条件装配。很多问题最后都能回到这条线上。
参考资料
- JavaGuide:https://javaguide.cn/
- JavaGuide GitHub:https://github.com/Snailclimb/JavaGuide