Spring 作为 Java 后端开发的核心框架,是面试中必考的重点内容。本文整理了 Spring 核心高频面试题,涵盖基础概念、核心原理、常用特性等维度,每道题均附详细解析和标准答案,帮你吃透考点、从容应对面试。
一、Spring 基础概念
1. 什么是 Spring 框架?Spring 的核心优势是什么?
解析 :Spring 是一个轻量级的 Java EE 开源框架,旨在简化企业级应用开发,核心是IoC(控制反转) 和AOP(面向切面编程)。
核心优势:
- 解耦:通过 IoC 容器管理对象依赖,替代硬编码的对象创建,降低组件间耦合度;
- 切面编程:AOP 支持将日志、事务、权限等通用逻辑与业务逻辑分离,提高代码复用性;
- 轻量级:核心容器轻量,无侵入式设计,无需依赖重量级应用服务器;
- 一站式:提供数据访问(Spring JDBC)、Web 开发(Spring MVC)、事务管理等一站式解决方案;
- 扩展性强:支持整合 MyBatis、Redis、Dubbo 等第三方框架。
2. Spring 框架的核心模块有哪些?
解析:Spring 框架由多个模块组成,核心模块如下:
- Core Container(核心容器):包含 Beans、Core、Context、SpEL 模块,是 Spring 的基础,实现 IoC 容器、Bean 管理核心功能;
- AOP + Aspects:提供 AOP 编程支持,整合 AspectJ 框架,实现切面逻辑;
- Data Access/Integration:包含 JDBC、ORM、OXM、JMS、Transaction 模块,支持数据库访问、事务管理;
- Web:包含 Web、Servlet、WebSocket、Portlet 模块,支持 Web 开发(如 Spring MVC);
- Test:提供 JUnit、TestNG 等测试框架的整合支持,便于单元测试和集成测试。
3. 什么是 IoC 容器?Spring IoC 容器的实现原理是什么?
解析:
- IoC(控制反转):将对象的创建、依赖注入的控制权从代码本身转移到 Spring 容器,由容器统一管理,核心是 "不再由开发者 new 对象,而是由容器分配对象";
- IoC 容器本质:是管理 Bean 的工厂,负责 Bean 的实例化、配置、依赖注入和生命周期管理;
- 核心实现 :
- 读取配置文件(XML / 注解),解析出 Bean 的定义信息;
- 通过反射机制创建 Bean 实例;
- 根据依赖关系完成 Bean 的依赖注入;
- 管理 Bean 的生命周期(初始化、销毁等);
- 核心接口 :
BeanFactory(基础 IoC 容器,懒加载)、ApplicationContext(高级容器,继承 BeanFactory,支持国际化、事件发布等,常用实现:ClassPathXmlApplicationContext、AnnotationConfigApplicationContext)。
二、Spring Bean 核心考点
4. Spring Bean 的作用域有哪些?默认作用域是什么?
解析:Bean 的作用域指 Bean 实例在 Spring 容器中的生命周期和可见范围,核心作用域如下:
表格
| 作用域 | 说明 |
|---|---|
| singleton | 默认作用域,整个容器中只有一个 Bean 实例,单例模式(容器启动时创建) |
| prototype | 原型模式,每次获取 Bean(如getBean())都会创建新实例 |
| request | 仅 Web 环境,每个 HTTP 请求创建一个新 Bean,请求结束后销毁 |
| session | 仅 Web 环境,每个 HTTP Session 创建一个 Bean,Session 过期后销毁 |
| application | 仅 Web 环境,整个 Web 应用共享一个 Bean,对应 ServletContext 的生命周期 |
| websocket | 仅 Web 环境,针对 WebSocket 会话创建 Bean |
注意 :singleton是默认作用域,prototype Bean 容器仅负责创建,不管理生命周期(销毁时不调用destroy方法)。
5. Spring Bean 的生命周期是什么?
解析:Spring Bean 完整生命周期(核心步骤):
- 实例化:容器通过反射创建 Bean 实例;
- 属性注入 :为 Bean 设置依赖的属性(如
setter方法、构造器注入); - 初始化前置处理 :调用
BeanPostProcessor的postProcessBeforeInitialization方法; - 初始化 :
- 若实现
InitializingBean接口,调用afterPropertiesSet()方法; - 若配置
init-method,执行指定的初始化方法;
- 若实现
- 初始化后置处理 :调用
BeanPostProcessor的postProcessAfterInitialization方法; - Bean 就绪:Bean 可被应用程序使用;
- 销毁 :
- 容器关闭时,若实现
DisposableBean接口,调用destroy()方法; - 若配置
destroy-method,执行指定的销毁方法。
- 容器关闭时,若实现
6. Spring Bean 的注入方式有哪些?
解析:核心注入方式(依赖注入 DI):
-
构造器注入 :通过构造方法注入依赖,推荐使用(强制依赖、不可变);
@Component public class UserService { private UserDao userDao; // 构造器注入 public UserService(UserDao userDao) { this.userDao = userDao; } } -
Setter 方法注入 :通过
setter方法注入,适用于可选依赖;@Component public class UserService { private UserDao userDao; // Setter注入 @Autowired public void setUserDao(UserDao userDao) { this.userDao = userDao; } } -
字段注入 :直接在字段上标注
@Autowired,简洁但耦合度高(不推荐);@Component public class UserService { // 字段注入 @Autowired private UserDao userDao; } -
注解注入 :
@Autowired(按类型注入)、@Resource(按名称注入)、@Qualifier(指定 Bean 名称)。
7. @Autowired 和 @Resource 的区别是什么?
解析:
| 维度 | @Autowired | @Resource |
|---|---|---|
| 来源 | Spring 自带注解 | JDK 自带(javax.annotation) |
| 匹配规则 | 默认按类型匹配,可配合 @Qualifier 按名称 | 默认按名称匹配,名称不存在则按类型 |
| 依赖是否必须 | 默认必须(找不到抛异常),可设required=false |
默认非必须(找不到返回 null) |
| 支持注入方式 | 字段、构造器、Setter 方法 | 字段、Setter 方法(不支持构造器) |
三、AOP 核心考点
8. 什么是 AOP?AOP 的核心概念有哪些?
解析:
- AOP(面向切面编程):将通用的、跨多个业务模块的逻辑(如日志、事务、权限)抽取为 "切面",在不修改业务代码的前提下,通过动态代理将切面逻辑织入业务流程,实现 "关注点分离";
- 核心概念 :
- 切面(Aspect):通用逻辑的封装(如日志切面、事务切面);
- 连接点(JoinPoint):程序执行的某个节点(如方法执行、异常抛出);
- 切入点(Pointcut):匹配连接点的规则(如指定包下的所有方法);
- 通知(Advice):切面的具体执行逻辑,包括:
- 前置通知(Before):方法执行前执行;
- 后置通知(After):方法执行后执行(无论是否异常);
- 返回通知(AfterReturning):方法正常返回后执行;
- 异常通知(AfterThrowing):方法抛出异常后执行;
- 环绕通知(Around):包裹方法执行,可自定义方法执行前后逻辑;
- 织入(Weaving):将切面逻辑融入目标对象的过程(Spring AOP 在运行时织入)。
9. Spring AOP 的实现原理是什么?
解析 :Spring AOP 基于动态代理实现,分为两种方式:
- JDK 动态代理 :
- 前提:目标对象实现了接口;
- 原理:通过
java.lang.reflect.Proxy生成代理类,代理类实现目标接口,调用InvocationHandler处理方法调用;
- CGLIB 动态代理 :
- 前提:目标对象未实现接口;
- 原理:通过 ASM 字节码框架生成目标类的子类,重写目标方法,织入切面逻辑;
- 注意 :Spring AOP 默认优先使用 JDK 动态代理,若目标类无接口则使用 CGLIB;可通过配置
proxy-target-class=true强制使用 CGLIB。
10. Spring AOP 和 AspectJ 的区别是什么?
解析:
| 维度 | Spring AOP | AspectJ |
|---|---|---|
| 实现方式 | 动态代理(运行时织入) | 字节码修改(编译期 / 类加载期织入) |
| 功能范围 | 仅支持方法级别的切面 | 支持方法、字段、构造器等多维度切面 |
| 性能 | 运行时生成代理,性能略低 | 编译期织入,性能更高 |
| 依赖 | 轻量级,无需额外编译步骤 | 需要特殊编译器(ajc),依赖更多 |
| 集成方式 | Spring 框架内置支持 | Spring 可整合 AspectJ 注解(如 @Aspect) |
四、事务管理
11. Spring 事务管理的核心接口有哪些?
解析 :Spring 事务管理核心接口(org.springframework.transaction包):
PlatformTransactionManager:事务管理器核心接口,定义事务的提交、回滚等操作,常用实现:DataSourceTransactionManager:JDBC/MyBatis 事务管理;HibernateTransactionManager:Hibernate 事务管理;JtaTransactionManager:分布式事务管理;
TransactionDefinition:定义事务属性(隔离级别、传播行为、超时时间等);TransactionStatus:表示事务的当前状态(是否活跃、是否回滚等)。
12. Spring 事务的传播行为有哪些?常用的传播行为是什么?
解析 :事务传播行为定义了 "一个事务方法调用另一个事务方法时,事务如何传递",核心传播行为(Propagation枚举):
| 传播行为 | 说明 |
|---|---|
| REQUIRED(默认) | 若当前有事务,则加入事务;若无,则新建事务 |
| REQUIRES_NEW | 新建事务,若当前有事务则挂起当前事务 |
| SUPPORTS | 若当前有事务则加入,若无则以非事务方式执行 |
| NOT_SUPPORTED | 以非事务方式执行,若当前有事务则挂起 |
| MANDATORY | 必须在事务中执行,若无事务则抛异常 |
| NEVER | 必须以非事务方式执行,若有事务则抛异常 |
| NESTED | 若当前有事务,则嵌套在当前事务中执行;若无,则新建事务 |
常用传播行为 :REQUIRED(大部分业务场景)、REQUIRES_NEW(如日志记录需独立事务)。
13. Spring 事务的隔离级别有哪些?
解析 :事务隔离级别解决并发事务的脏读、不可重复读、幻读问题,核心级别(Isolation枚举):
| 隔离级别 | 说明 |
|---|---|
| DEFAULT | 采用数据库默认隔离级别(MySQL 默认 REPEATABLE_READ,Oracle 默认 READ_COMMITTED) |
| READ_UNCOMMITTED | 最低级别,允许读取未提交的数据(可能脏读、不可重复读、幻读) |
| READ_COMMITTED | 允许读取已提交的数据(避免脏读,可能不可重复读、幻读) |
| REPEATABLE_READ | 保证多次读取同一数据结果一致(避免脏读、不可重复读,可能幻读) |
| SERIALIZABLE | 最高级别,串行化执行(避免所有并发问题,性能最低) |
14. 为什么 Spring 事务会失效?常见原因有哪些?
解析:Spring 事务基于 AOP 实现,以下场景会导致事务失效:
- 方法非 public:Spring AOP 仅拦截 public 方法,private/protected 方法的事务注解无效;
- 自调用问题:同一个类中,非事务方法调用事务方法,AOP 无法拦截(未走代理);
- 异常类型不匹配 :默认仅捕获
RuntimeException,若抛出CheckedException(如IOException)且未配置rollbackFor,事务不回滚; - 手动捕获异常:方法内捕获异常但未抛出,事务无法感知异常,不会回滚;
- 传播行为设置错误 :如设置
NOT_SUPPORTED(非事务执行); - 数据源未配置事务管理器 :未将数据源与
DataSourceTransactionManager绑定; - Bean 未被 Spring 管理 :如未加
@Component、@Service等注解,AOP 无法代理。
五、Spring MVC
15. Spring MVC 的核心组件有哪些?工作流程是什么?
解析:
核心组件
DispatcherServlet:前端控制器,接收所有请求并分发;HandlerMapping:根据请求 URL 匹配处理器(Controller 方法);HandlerAdapter:适配并执行处理器方法;ViewResolver:解析视图名,返回 View 对象;HandlerExceptionResolver:处理异常。
工作流程
- 客户端发送请求至
DispatcherServlet; DispatcherServlet通过HandlerMapping找到对应的 Handler;DispatcherServlet通过HandlerAdapter执行 Handler,返回ModelAndView;DispatcherServlet通过ViewResolver解析ModelAndView,生成 View;- View 渲染数据(Model),返回响应给客户端。
16. @RequestMapping 注解的作用是什么?常用属性有哪些?
解析:
@RequestMapping:用于映射 HTTP 请求到 Controller 的方法,可标注在类 / 方法上;- 常用属性:
value/path:指定请求 URL(如value = "/user/list");method:指定请求方式(如method = RequestMethod.GET);params:指定请求参数(如params = "id",要求必须携带 id 参数);headers:指定请求头(如headers = "Content-Type=application/json");consumes:指定请求体类型(如consumes = "application/json");produces:指定响应体类型(如produces = "application/json")。
简化注解 :@GetMapping、@PostMapping、@PutMapping、@DeleteMapping(分别对应 GET/POST/PUT/DELETE 请求)