一、Spring 核心基础
1. 什么是 Spring?核心思想?
Spring 是轻量级、一站式、分层的 Java 开发框架。 两大核心:
- IoC 控制反转:对象创建、依赖管理交给容器,解耦
- AOP 面向切面:无侵入扩展功能,日志、事务、权限
2. 什么是 IoC、DI?关系?
IoC(控制反转) : 把对象的创建、依赖管理、生命周期控制权 从程序员代码反转给 Spring 容器。
DI(依赖注入) : IoC 的实现方式,容器自动给 Bean 注入依赖对象。
一句话:IoC 是思想,DI 是实现
3. DI 三种注入方式
- 构造器注入(官方推荐)
- 保证对象初始化完成、不可变、线程安全
- 循环依赖最优解
- Set 方法注入
- 适合可选依赖
- 字段注入 @Autowired
- 简洁但不利于解耦、单元测试、容易循环依赖
4. 为什么推荐构造器注入?
- 保证必填依赖不为空
- 保证对象初始化完成即可用
- 有效避免循环依赖
- Spring 官方推荐
5. Bean 的作用域
- singleton(默认) :整个容器单例
- prototype :每次获取新建对象
- request:一次请求一个 Bean
- session:一个会话一个 Bean
- application:全局 web 容器
- websocket:websocket 会话
6. Spring 单例 和 设计模式单例区别
- 设计模式单例:全局 ClassLoader 唯一
- Spring 单例:容器内唯一,多容器多实例
7. Bean 完整生命周期
- 实例化:反射 new 对象
- 属性填充:DI 依赖注入
- 初始化前置:BeanPostProcessor before
- 初始化:InitializingBean / @PostConstruct
- 初始化后置:BeanPostProcessor after
- 销毁:容器关闭执行 @PreDestroy / DisposableBean
口诀:实例→赋值→前置→初始化→后置→销毁
8. @Component、@Service、@Controller、@Repository 区别
功能完全一样,只是语义区分
- @Service:业务层
- @Controller:控制层
- @Repository:DAO 层
- @Component:通用组件
9. @Component 和 @Bean 区别(必考)
- @Component :作用在类,Spring 扫描自动创建 Bean(自己写的类)
- @Bean :作用在方法,手动创建 Bean(第三方类、配置类)
10. Spring 循环依赖 以及解决方案
循环依赖:A 依赖 B,B 依赖 A
- 构造器注入:无法解决,直接报错
- set / 字段注入:三级缓存解决
三级缓存原理(满分答案)
- 一级缓存:完全初始化好的 Bean
- 二级缓存:实例化完成、未赋值 Bean
- 三级缓存:ObjectFactory,提前暴露 Bean 引用
核心:先曝光引用,再完成赋值,解决循环依赖
二、Spring AOP 面试全集
1. 什么是 AOP?
面向切面编程 ,在不修改源码的前提下,对方法进行增强。 用于:日志、权限、事务、限流、缓存
2. AOP 核心术语
- 切点 Pointcut:要拦截的方法
- 通知 Advice:增强代码(前置、后置、异常、环绕)
- 切面 Aspect:切点 + 通知
- 连接点 JoinPoint:所有可拦截的方法
- 织入 Weaving:把切面逻辑植入目标方法
3. 五种通知执行顺序
- @Before 前置
- @Around 环绕(最强大)
- @AfterReturning 正常返回
- @After 最终后置
- @AfterThrowing 异常通知
4. JDK 动态代理 vs CGLIB 代理
- JDK 动态代理
- 必须有接口
- 代理接口方法
- CGLIB 代理
- 无需接口,继承子类代理
- 代理类所有方法
- Spring 默认优先 JDK,无接口自动 CGLIB
5. AOP 为什么事务、日志能生效?
Spring 通过动态代理,在方法前后织入增强逻辑。
6. AOP 失效场景
- 内部调用(this. 方法 ())不走代理,AOP 失效
- 方法private/static/final 无法代理
- 类没有交给 Spring 管理
三、Spring 事务 面试天花板
1. Spring 事务底层原理
AOP 动态代理
- 调用方法前开启事务
- 正常执行提交
- 异常回滚
2. 事务四大隔离级别
- READ_UNCOMMITTED:读未提交(脏读、不可重复、幻读)
- READ_COMMITTED:读已提交(默认,解决脏读)
- REPEATABLE_READ:可重复读(MySQL 默认,解决不可重复读)
- SERIALIZABLE:串行化(全部解决、性能最差)
3. 七种传播机制
- REQUIRED(默认):有事务就加入,没有新建
- SUPPORTS:有就用,没有就非事务
- MANDATORY:必须在事务内,否则报错
- REQUIRES_NEW :新建独立事务,挂起旧事务
- NOT_SUPPORTED:强制非事务
- NEVER:必须非事务,否则报错
- NESTED:嵌套事务,保存点回滚
4. @Transactional 失效 100% 必考坑点
- 方法非 public 失效
- 内部调用 this.xxx () 失效(无代理)
- 异常不是 RuntimeException,默认不回滚
- 异常被 try-catch 吃掉,无法触发回滚
- 数据库引擎不支持事务(MyISAM)
- 传播机制配置错误
5. 怎么解决事务内部调用失效?
- 自己注入自己(AopContext 获取代理对象)
- 拆分方法到不同类
四、SpringMVC 全套面试题
1. SpringMVC 执行完整流程
- 客户端发起请求
- DispatcherServlet 前端控制器拦截所有请求
- 调用 HandlerMapping 找到对应 Controller
- 调用 HandlerAdapter 执行 Controller 方法
- 方法返回 ModelAndView
- 视图解析器渲染视图
- 响应给前端
2. DispatcherServlet 核心作用
统一入口、分发请求、调度所有组件
3. @RequestParam 和 @RequestBody 区别
- @RequestParam :接收表单、url 参数(键值对)
- @RequestBody :接收JSON 体,只能 POST
4. GET、POST 区别、参数接收区别
5. 拦截器 Interceptor vs 过滤器 Filter
- Filter:Servlet 层,拦截所有请求,先执行
- Interceptor :SpringMVC 层,只拦截 Controller 执行顺序:Filter → Interceptor → Controller
五、SpringBoot 高频面试
1. SpringBoot 核心优势
- 自动配置
- 内嵌 Tomcat,无需部署 war
- 简化依赖、starter 启动器
- 无需 xml 配置
2. 核心注解 @SpringBootApplication
由三个注解组成:
- @Configuration:配置类
- @EnableAutoConfiguration:自动配置
- @ComponentScan:包扫描
3. 自动配置原理(SPI + 条件注解)
- 加载 META-INF/spring.factories
- 根据条件注解按需自动装配 Bean
- 开发者配置 优于 自动配置
4. 配置文件优先级
properties > yml 同级别覆盖 外部配置 > 内部配置
5. SpringBoot 启动流程
- 初始化 SpringApplication
- 准备环境、加载配置
- 刷新容器 refresh ()
- 启动内嵌 Tomcat
- 执行 Runner
6. Starter 原理
约定大于配置 场景启动器自动引入依赖、自动装配 Bean
六、Spring 源码高频面试
1. refresh () 核心 12 大步
- 刷新前准备
- 初始化 BeanFactory
- 后置处理 BeanFactory
- 注册 Bean 后置处理器
- 初始化消息资源
- 初始化事件分发器
- 扫描注册所有 Bean 定义
- 初始化非懒加载单例 Bean
- 完成上下文刷新
2. Bean 工厂 和 上下文区别
- BeanFactory:底层 Bean 工厂,功能简单、延迟加载
- ApplicationContext:高级容器,继承 BeanFactory,多了国际化、事件、资源、AOP
3. Spring 事件机制
发布 - 订阅模式:自定义事件、监听事件
七、Spring 高频八股总结
1. Spring 为什么解耦?
IoC 容器管理对象,AOP 横向扩展功能,彻底消除硬编码依赖。
2. 三级缓存解决循环依赖核心?
提前暴露对象引用
3. 事务失效最常见原因?
内部调用、非 public、异常被捕获
4. AOP 和 OOP 区别?
OOP 纵向封装,AOP 横向增强
5. SpringBean 单例线程安全吗?
不安全 单例 Bean 全局共享,成员变量多线程并发修改会冲突,解决方案:ThreadLocal、无状态设计
八、面试官最爱追问的 10 个压轴题
- 讲讲三级缓存每一层具体作用?
- 为什么构造器注入不能解决循环依赖?
- 事务传播机制 REQUIRES_NEW 和 NESTED 区别?
- 内部调用事务失效怎么彻底解决?
- SpringBean 线程安全问题怎么处理?
- AOP 环绕通知和其他通知区别?
- Spring 自动配置条件注解有哪些?
- 为什么 Spring 默认单例?
- SpringMVC 九大组件你知道哪些?
- 说说 Spring 的事件驱动模型?