Spring Framework 核心面试速查。详细原理见下方 Spring Framework 专题三篇。
相关学习笔记
| 专题 | 笔记 |
|---|---|
| Spring 全家桶 | Spring 全家桶 |
| IoC 与依赖注入 | Spring IoC 与依赖注入 |
| AOP 与事务 | Spring AOP 与事务 |
| Spring MVC | Spring MVC 基础 |
| Spring Boot | Spring Boot 面试题 30 道 |
| Spring Cloud | Spring Cloud 面试题 49 道 |
1. 谈谈 Spring IoC 的理解,原理与实现?
IoC(Inversion of Control,控制反转) 指对象的创建权与依赖组装权从业务代码转移到 Spring 容器。业务类不再自己 new 依赖,而是声明「我需要什么」,由容器在运行时注入——这种注入方式叫 DI(Dependency Injection,依赖注入),是 IoC 最常见的实现。
为什么要 IoC
- 降低耦合:换实现(Mock、缓存版)只改配置或注解,不改业务源码
- 便于测试:测试时可注入 Stub / Mock Bean
- 统一管理生命周期:单例、原型、初始化/销毁回调由容器统一调度
原理(简化流程)
加载配置 / 组件扫描 → 解析 BeanDefinition(类、作用域、依赖等元数据) → 实例化 Bean → 属性/构造器注入(DI) → BeanPostProcessor 处理(AOP 代理常在此阶段生成) → 初始化回调(@PostConstruct、InitializingBean) → Bean 就绪,可被注入使用实现方式(注册 Bean)
| 方式 | 示例 | 场景 |
|---|---|---|
| XML | <bean id="..." class="..."/> | 老项目、显式配置 |
| 组件扫描 | @Component / @Service + @ComponentScan | 主流业务类 |
| Java 配置 | @Configuration + @Bean | 第三方类、复杂构造 |
Spring Boot 启动时,本质是创建并 refresh 一个 ApplicationContext,完成扫描、自动配置与 Bean 注册后再对外服务。→ 详见 IoC 与依赖注入
2. @Autowired 和 @Resource 关键字的区别?
两者都用于依赖注入,但来源、默认匹配规则、配套注解不同。
@Autowired | @Resource | |
|---|---|---|
| 来源 | Spring 自有(org.springframework.beans.factory.annotation) | JSR-250 标准(javax.annotation / jakarta.annotation) |
| 默认匹配 | 先按类型(byType) | 先按名称(byName),找不到再按类型 |
| 指定名称 | 配合 @Qualifier("beanName") | 直接 @Resource(name = "beanName") |
| 是否必填 | required = false 可允许找不到 Bean | 默认必须找到,否则抛异常 |
| 注入点 | 字段、构造器、方法、参数 | 字段、setter 方法(不支持构造器参数) |
@Autowired 解析顺序(按类型)
- 容器中该类型只有一个 Bean → 直接注入
- 多个同类型 → 看字段/参数名是否与 bean 名称一致 →
@Primary→@Qualifier required = false→ 找不到时不报错
选型建议
- Spring 项目、构造器注入、需要
Optional/required = false→ 优先@Autowired(Spring 4.3+ 单构造器可省略) - 明确按 bean 名称注入、与 JSR 规范对齐 →
@Resource(name = "...")
3. 依赖注入的方式有几种,各是什么?
Spring 支持三种注入方式(按推荐程度排序):
| 方式 | 写法 | 特点 |
|---|---|---|
| 构造器注入 | 构造器参数 + @Autowired(可省略) | 首选:依赖 final 不可变、必填、单元测试友好 |
| Setter 注入 | setter 方法 + @Autowired | 适合可选依赖、遗留代码改造 |
| 字段注入 | 字段上直接 @Autowired | 写法简洁,但不利于测试、无法 final,不推荐 |
@Servicepublic class OrderService { private final OrderRepository repo;
// 构造器注入(推荐) public OrderService(OrderRepository repo) { this.repo = repo; }}补充:配置项注入常用 @Value("${key:default}");复杂配置在 Boot 里更推荐 @ConfigurationProperties。→ 详见 依赖注入方式
4. 说说你对 Spring MVC 的理解
Spring MVC 是基于 Servlet 的 Web 层框架,负责把 HTTP 请求映射到 Controller 方法,完成参数绑定、业务调用、返回视图或 JSON。
核心角色
| 组件 | 职责 |
|---|---|
| DispatcherServlet | 前端控制器,统一接收请求并调度 |
| HandlerMapping | 根据 URL 找到对应的 Controller 方法 |
| HandlerAdapter | 适配并调用 Controller 方法 |
| ViewResolver | 解析视图名(REST 项目常直接返回 JSON,跳过视图) |
| HttpMessageConverter | 将对象序列化为 JSON/XML 等 |
请求处理流程(简化)
Client → DispatcherServlet → HandlerMapping(找 Handler) → HandlerAdapter(调 Controller) → Service / 业务层 → 返回 ModelAndView 或 @ResponseBody 数据 → HttpMessageConverter 写回响应与三层架构的关系
- Controller:接 HTTP、参数校验、返回 DTO/VO
- Service:业务逻辑、事务边界(
@Transactional) - Mapper/DAO:数据访问
Spring Boot 的 spring-boot-starter-web 自动配置了 DispatcherServlet、Jackson、内嵌 Tomcat 等,本质仍是 Spring MVC,只是省去大量 XML 与手动装配。→ 详见 Spring MVC 基础
5. Spring MVC 常用的注解有哪些?
类级别
| 注解 | 作用 |
|---|---|
@Controller | 标记控制器;方法返回值可作视图名 |
@RestController | @Controller + @ResponseBody,REST API 常用 |
@RequestMapping | 类或方法上的路径映射;可指定 HTTP 方法、consumes/produces |
方法级别(路径映射,Boot 中更常用细分注解)
| 注解 | 等价于 |
|---|---|
@GetMapping | @RequestMapping(method = GET) |
@PostMapping | @RequestMapping(method = POST) |
@PutMapping / @DeleteMapping / @PatchMapping | 对应 HTTP 动词 |
参数绑定
| 注解 | 作用 |
|---|---|
@RequestParam | 查询参数,如 ?id=1;可设 required、defaultValue |
@PathVariable | 路径变量,如 /users/{id} |
@RequestBody | 请求体 JSON → Java 对象(依赖 Jackson) |
@RequestHeader | 请求头 |
@CookieValue | Cookie 值 |
@ModelAttribute | 绑定表单或模型属性 |
响应与校验(常一起出现)
| 注解 | 作用 |
|---|---|
@ResponseBody | 返回值直接写回 HTTP 体(@RestController 已包含) |
@ResponseStatus | 指定 HTTP 状态码 |
@Valid / @Validated | 触发 JSR-303 参数校验(配合 @NotNull 等) |
6. 谈谈你对 Spring 的 AOP 理解
AOP(Aspect-Oriented Programming,面向切面编程) 把日志、权限、事务、监控等横切关注点从业务方法中剥离,通过「切面」统一织入,避免每个方法重复写相同代码。
核心术语
| 术语 | 含义 |
|---|---|
| 切面(Aspect) | 横切逻辑的模块,如 @Aspect 类 |
| 连接点(Join Point) | 程序执行中的某个点(如方法调用、异常抛出) |
| 切点(Pointcut) | 匹配哪些连接点,如 execution(* com.example.service.*.*(..)) |
| 通知(Advice) | 在切点上执行的动作:前置、后置、环绕、异常、最终 |
Spring AOP 的实现:代理
Spring AOP 默认基于运行时代理,不修改字节码:
| JDK 动态代理 | CGLIB | |
|---|---|---|
| 条件 | 目标类实现接口 | 可代理类(类、方法非 final) |
| 方式 | 基于接口生成代理对象 | 生成目标类的子类 |
| Spring 选择 | 有接口时优先 JDK | 无接口时用 CGLIB |
典型应用
- 声明式事务:
@Transactional通过 AOP 在方法前后开启/提交/回滚事务 - 统一日志、权限校验、性能监控、缓存(如
@Cacheable)
注意
- Spring AOP 是方法级别的,不能像 AspectJ 那样织入字段赋值等所有连接点
- 同类内部自调用(
this.method())不走代理,@Transactional等会失效 → 见 AOP 与事务
7. 说说 Spring 中 ApplicationContext 和 BeanFactory 的区别
两者都是 IoC 容器接口;ApplicationContext 继承自 BeanFactory,是功能更全的超集。日常开发几乎只用 ApplicationContext。
| BeanFactory | ApplicationContext | |
|---|---|---|
| 定位 | 最基础的 IoC 容器 | BeanFactory 的超集 |
| Bean 加载 | 延迟加载(getBean 时才创建) | 启动时一次性预实例化所有单例 Bean(除非 @Lazy) |
| 扩展能力 | 基础 DI | 国际化、事件发布、资源访问(classpath 文件等) |
| BeanPostProcessor | 需手动注册 | 自动注册 BeanPostProcessor、BeanFactoryPostProcessor |
| AOP 集成 | 需额外配置 | 启动流程中自动完成,AOP 代理依赖 BeanPostProcessor |
| 典型实现 | DefaultListableBeanFactory | AnnotationConfigApplicationContext、ClassPathXmlApplicationContext |
| 使用场景 | 框架内部、极少业务直接写 | 开发常用;Boot 启动即 ApplicationContext |
记忆要点
- BeanFactory = 「能管 Bean 的最小容器」
- ApplicationContext = BeanFactory + 企业级特性 + 启动时就把单例 Bean 建好
- Spring Boot 启动后得到的
ApplicationContext(如AnnotationConfigServletWebServerApplicationContext)完成组件扫描、自动配置、Bean 注册后再对外提供服务