这篇文章按照 SpringBoot 面试高频题整理,从 Spring 核心架构出发,围绕 IOC、AOP、Bean 管理、事务机制、自动装配、MVC 请求流程、设计模式以及启动流程等核心模块展开。目标不是简单背诵注解和源码,而是理解 SpringBoot 背后的运行机制,能够用清晰的逻辑回答面试中常见的原理问题。
IOC和AOP
IOC
IOC,即控制反转,指的是将对象的控制权交给 Spring 容器,容器负责创建和管理对象,我们只需要接受容器注入的对象。
优点:
- 降低耦合:在非 IOC 的传统编程中,对象的创建和依赖管理硬编码在业务逻辑中,与具体实现类强绑定,一旦更换实现类,就需要改动业务代码。
- 不需要重复创建相同的对象浪费内存:Spring 容器中的 Bean 对象默认是单例的。
AOP
AOP,即面向切面编程,用作无侵入式的代码增强,一般对公共的行为或者逻辑进行抽取,将横切逻辑和业务逻辑分离,提升代码复用性和可维护性。
应用场景:
- 权限验证
- 记录操作日志
- Spring事务的实现即AOP
实现方式:动态代理 - JDK动态代理:基于接口,生成接口的代理类
- CGLIB代理:基于类,通过继承目标类生成字类,重写方法增强
Spring AOP 根据目标对象是否实现接口,选择不同的代理机制:
- 实现了接口:使用 JDK 动态代理。
- 未实现接口:使用 CGLIB 代理。
常见注解
| Spring | Spring MVC | Spring Boot | |
|---|---|---|---|
| 定位 | 核心框架 | Web模块 | 快速开发工具 |
| 作用 | 管理对象、事务、AOP | 处理HTTP请求 | 简化Spring配置 |
| 是否能单独用 | 可以 | 依赖Spring | 基于Spring |
| 解决问题 | 企业开发基础 | Web接口开发 | 快速启动项目 |
| 包含关系 | 基础 | Spring的一部分 | 基于Spring |
Spring事务
主要分为编程式事务和声明式事务两种
编程式事务
基于底层的 API(如 platform transition manager、transition definition 等核心接口),开发者完全可以通过编程的方式来进行事务管理。
编程式事务方式需要手动管理事务的开启、提交、回滚等操作。
声明式事务
Spring ⽀持声明式事务管理,即@Transactional注解,声明式事务管理建⽴在AOP之上。
其本质是通过AOP功能,对加了@Transactional注解的⽅法前后进⾏拦截,
在执⾏⽬标⽅法之前开启事务,在执⾏完⽬标⽅法之后根据执⾏情况提交事务或者回滚事务。
声明式事务的优点
声明式事务帮助我们节省了很多嗲吗,自动帮我们进行事务的开启,提交以及回滚等操作。
声明式事务管理使用了AOP实现的,本质就是在目标方法执行前后进行拦截。在目标方法执行前加入或创建一个事务,在执行方法执行后,根据情况选择提交或是回滚事务。
使⽤这种⽅式,对代码没有侵⼊性,⽅法内只需要写业务逻辑就可以了。
Spring Bean的作用域
Single(单例)作用域:
每一次从 IOC 容器获取指定 Bean 对象时,都会返回同一个实例对象。
适用场景:无状态 Bean,如工具类、配置类、服务类等。Prototype(原型)作用域:
每一次从 IOC 容器获取指定 Bean 对象时,都会返回一个新的实例对象。
适用场景:有状态Bean,需要隔离状态的场景。
但在基于 Spring 框架下的 Web 应用中,增加了三种作用域:
- Request 请求作用域:针对每一次 HTTP 请求,都会创建一个新的 bean。
- Session 会话作用域:针对 session 会话,同一个 session 共享同一个 bean 实例,不同的 session 则产生不同的 bean 实例。
- Application 应用作用域:整个 web 应用中共享一个实例。
SpringBoot自动装配原理
Spring Boot 自动配置的核心就是 @EnableAutoConfiguration 注解。它通过 @Import 引入了 AutoConfigurationImportSelector 类,会去扫描 classpath 下所有 jar 包里的文件,找出里面声明的自动配置类,然后根据条件注解决定哪些配置要加载。
整个流程是这样的:
- Spring Boot 启动时,@SpringBootApplication 里包含的 @EnableAutoConfiguration 生效。
- 触发 AutoConfigurationImportSelector 去读取 factories 文件,拿到一堆候选配置类。
- 逐个检查这些类上的条件注解,只有条件注解全部满足的配置类,才会真正地加载并注册到容器里。
Spring MVC执行流程
Spring MVC 是 Spring 框架中专门用来做 Web 开发的模块,核心思想是 MVC 分层:Model 负责数据、View 负责展示、Controller 负责接收请求和协调。
它最大的价值在于引入了一个前端控制器DispatcherServlet,所有请求都先经过它,由它来调度后续流程。以前用纯 Servlet 开发,每个 URL都得写一个Servlet类,几十个接口就是几十个类,web.xml配置一大坨。有了DispatcherServlet后,只需要在方法上加个@RequestMapping 注解就能搞定URL映射,代码量直接砍掉80%。
Spring MVC 的分层是这样的:
1) Controller 层:接收 HTTP 请求,调用 Service 处理业务,把结果返回给视图或直接返回JSON
2)Service 层:处理业务逻辑,事务控制一般也在这层
3) Repository/DAO层:跟数据库打交道,执行 SQL
4) View层:渲染页面,可以是JSP、Thymeleaf,或者现在流行的前后端分离直接返回JSON
- 用户发出请求到前端控制器
- 前端控制器收到请求调用(处理器引射器)
- 处理器引射器找到具体的处理器,返回处理器执行链(包括处理器和拦截器)给前端控制器
- 前端控制器调用(处理器适配器)
- 处理器适配器靖哥哥适配器调用具体的处理器
- 在方法上添加了@ResponseBody,因此通过HttpMessageConverter来返回结果转换为JSON并响应
Spring中的设计模式
面试官问:;了解那些设计模式时,可以说Spring的源码,其中用了什么设计模式
单例模式
默认情况,Spring IOC容器中会确保每一个Bean只有一个实例,该实例在整个应用中被共享使用
好处:对象复用,避免频繁创建和销毁对象的开销,减少内存占用和GC压力
实现原理
- 在Spring容器启动时,会创建非懒加载的Bean,并且将其存入缓存中,后续对Bean的请求会从缓存(ConcurrentHashMap)中获取。
工厂模式
Spring IOC 容器就像是一个工厂,封装了创建对象的细节。我们通过 getBean 方法从工厂中获取对象,其好处在于:
- 解除了耦合,实现了对象的创建和使用分离。
- 集中管理对象的生命周期。
代理模式
Spring AOP(面向切面编程)使用了代理模式。当配置了一个切面,Spring 会创建目标对象的代理,拦截对应的方法调用,在方法执行前后进行增强。
其好处是:无侵入式代码增强。
责任链模式
一个请求过程中,可嫩几个过很多拦截器,每个拦截器=做的事情不一样,这就是责任链,SpringMVC通过责任来拿模式将请求处理流程拆解为多个可插拔的拦截器节点
好处:可以灵活的拓展处理流程,若将所有拦截逻辑硬编码在单一处理流程中,会导致代码臃肿,那一维护,而责任来拿每个节点只需要关注自己的职责。
观察者模式
观察者模式,也称为发布-订阅模式,Spring 中也有对应的机制: 事件发布-监听机制
存在着⼀对多的关系,多个观察者监听(订阅)某个事件,当这个事件被发布时,多个观察者就能监听到,进⽽去做观察者的逻辑
好处:使⽤该机制可以将相互耦合的代码解耦,从⽽⽅便功能的拓展和调整。
主逻辑只需要执⾏关键路径,附带的(不断扩展的)操作可以由观察者监听事件发布后完成
SpringBoot启动流程
- 入口启动,初始化配置
执行main方法,调用SpringApplication,run;加载spring.factories中配置的初始化器和监听器 - 创建应用程序上下文,创建Bean工厂对象
- 刷新应用程序上下文
核心方法refresh:
配置工厂对象(上下文类加载器,对象发布处理器)
注册并实例化bean工厂发布处理器,并且调用这些处理器,对包扫描
注册并实例化bean发布处理器
初始化一些上下文
实例化所有bean工厂缓存的bean对象
发布通知-上下文刷新完成(启动tomcat服务器) - 启动完成
发布ApplicationReadyEvent 事件通知监听者启动程序已完成。