java面试中经常会问到的spring问题有哪些(基础版)
文章目录
- 一、Spring 核心概念与 IOC 容器
- 二、AOP(面向切面编程)
- 三、Spring 事务管理
- 四、Spring 核心组件与注解
- 五、Spring MVC 与 Web 相关
- 六、Spring Boot 相关
- 总结
Spring 是 Java 后端开发的核心框架,面试中涉及的问题主要围绕绕其核心特性、底层原理、重要组件及实战应用。以下是高频考点题及核心考点及解析:
一、Spring 核心概念与 IOC 容器
- 什么是 Spring?它的核心特性有哪些?
- Spring 是一个轻量级开源框架,核心是 IOC(控制反转) 和 AOP(面向切面编程),用于简化企业级应用开发。
- 核心特性:IOC 容器、AOP 支持、依赖注入、事务管理、Spring MVC、集成各种框架(MyBatis、Hibernate 等)、简化测试(如
@SpringBootTest
)。
- 什么是 IOC(控制反转)和 DI(依赖注入)?两者的关系是什么?
- IOC:传统开发中,对象由开发者主动
new
创建(控制正转);Spring 中,对象的创建、管理由 Spring 容器负责(控制权反转给容器)。- DI:IOC 的具体实现方式,容器通过构造函数、setter 方法或字段,将依赖对象注入到目标对象中(如
@Autowired
注入服务)。- 关系:DI 是 IOC 的实现手段,IOC 是 DI 的设计思想。
- Spring IOC 容器的初始化过程?
- 加载配置(XML 或注解扫描)→ 解析配置生成
BeanDefinition
(存储 Bean 元信息:类名、依赖、作用域等)→ 实例化 Bean(getBean()
时触发,默认懒加载)→ 依赖注入(填充属性)→ 初始化(执行init-method
或InitializingBean
接口)→ 放入容器缓存。
- Spring 中的 Bean 作用域有哪些?默认是什么?
singleton
(默认):容器中只有一个实例,全局共享。prototype
:每次getBean()
都创建新实例。request
:每个 HTTP 请求创建一个实例(Web 环境)。session
:每个会话创建一个实例(Web 环境)。application
:全局应用级实例(Web 环境,类似 singleton 但与 ServletContext 绑定)。- 考察点:
singleton
与prototype
的区别、线程安全性(singleton
需注意状态修改的线程安全)。
- Bean 的生命周期?
- 实例化(调用构造函数)→ 属性注入(
setter
或字段赋值)→ 初始化前(BeanPostProcessor.postProcessBeforeInitialization
)→ 初始化(@PostConstruct
、InitializingBean.afterPropertiesSet()
、init-method
)→ 初始化后(BeanPostProcessor.postProcessAfterInitialization
)→ 使用中 → 销毁(@PreDestroy
、DisposableBean.destroy()
、destroy-method
)。
二、AOP(面向切面编程)
- 什么是 AOP?AOP 的核心概念有哪些?
- AOP:通过“横切”技术,将日志、事务、权限等通用功能(切面)与业务逻辑分离,实现代码复用和解耦。
- 核心概念:
- 切面(Aspect):封装的通用功能(如日志切面)。
- 连接点(JoinPoint):程序执行过程中的点(如方法调用、字段赋值)。
- 切入点(Pointcut):筛选连接点的规则(如
execution(* com.xxx.service.*(..))
匹配服务层所有方法)。- 通知(Advice):切面的具体动作(
@Before
前置、@After
后置、@Around
环绕等)。- 目标对象(Target):被切面增强的对象。
- Spring AOP 与 AspectJ 的区别?
- Spring AOP:基于动态代理(JDK 动态代理或 CGLIB),运行时增强,只能增强方法级别的连接点,轻量级。
- AspectJ:基于编译期或类加载期增强(字节码修改),支持字段、构造函数等更多连接点,功能更强但复杂度高。
- Spring 中可通过
@Aspect
注解集成 AspectJ 的语法,但默认仍用 Spring AOP 的动态代理实现。
- Spring AOP 的动态代理方式?什么时候用 JDK 代理?什么时候用 CGLIB?
- JDK 动态代理:基于接口,代理类实现目标接口,通过反射调用目标方法(目标类必须有接口)。
- CGLIB 代理:基于继承,代理类继承目标类,重写方法实现增强(目标类无接口时使用)。
- 切换逻辑:Spring 5 后默认策略:若目标类有接口则用 JDK 代理,否则用 CGLIB;可通过
proxyTargetClass = true
强制使用 CGLIB。
- 如何用 AOP 实现事务管理或日志记录?
- 日志记录示例:定义切面类,用
@Pointcut
匹配需记录日志的方法,@Around
通知中记录方法入参、返回值和耗时。- 事务管理:Spring 内置事务切面
TransactionInterceptor
,通过@Transactional
注解标记事务方法,AOP 自动在方法执行前后开启、提交或回滚事务。
三、Spring 事务管理
- Spring 事务的隔离级别有哪些?默认是什么?
- 基于数据库隔离级别扩展,共 5 种:
DEFAULT
(默认):使用数据库默认隔离级别(MySQL 默认为REPEATABLE_READ
,Oracle 默认为READ_COMMITTED
)。READ_UNCOMMITTED
:读未提交(可能脏读、不可重复读、幻读)。READ_COMMITTED
:读已提交(避免脏读,可能不可重复读、幻读)。REPEATABLE_READ
:可重复读(避免脏读、不可重复读,可能幻读)。SERIALIZABLE
:串行化(完全避免三种问题,性能极低)。
- Spring 事务的传播行为有哪些?常用的是哪几个?
- 传播行为:多个事务方法嵌套调用时,事务的传播规则(如是否新建事务、是否加入现有事务)。
- 常用传播行为:
REQUIRED
(默认):若当前有事务则加入,否则新建事务。REQUIRES_NEW
:无论当前是否有事务,都新建事务(原有事务挂起)。SUPPORTS
:若当前有事务则加入,否则以非事务方式执行。NESTED
:若当前有事务,则在嵌套事务中执行(独立提交/回滚);否则新建事务。
@Transactional
注解的工作原理?哪些情况会导致事务失效?
- 原理:通过 AOP 动态代理,生成代理类,在目标方法执行前后添加事务管理逻辑(开启、提交、回滚)。
- 事务失效场景:
- 方法不是
public
(@Transactional
只对 public 方法生效)。- 自调用(同一类中方法调用,未经过代理类,AOP 增强失效)。
- 异常被捕获(未抛出异常,事务无法感知需要回滚)。
- 错误的异常类型(默认只回滚
RuntimeException
和Error
, checked 异常不回滚)。- 传播行为配置错误(如
NOT_SUPPORTED
以非事务方式执行)。
- 如何解决分布式事务问题?Spring 有哪些方案?
- 分布式事务:跨多个数据库或服务的事务(如订单服务和库存服务分属不同数据库)。
- Spring 相关方案:
- 2PC(两阶段提交):基于
JtaTransactionManager
,但性能差,适合强一致性场景。- TCC(Try-Confirm-Cancel):通过业务代码手动实现事务提交/回滚(如
Seata
框架)。- 可靠消息队列:基于最终一致性,通过消息确认机制确保事务完成(如 RocketMQ 的事务消息)。
四、Spring 核心组件与注解
@Autowired
、@Resource
、@Inject
的区别?
@Autowired
:Spring 注解,默认按类型(byType
)注入,结合@Qualifier
按名称(byName
)注入,支持required = false
(非必须)。@Resource
:JDK 注解(javax.annotation
),默认按名称注入,名称匹配失败则按类型注入,支持name
和type
属性。@Inject
:JSR-330 注解,需导入依赖,功能类似@Autowired
,但无required
属性。
@Component
、@Service
、@Controller
、@Repository
的区别?
- 均用于标识 Spring 组件,
@Service
(服务层)、@Controller
(控制层)、@Repository
(数据访问层)是@Component
的特例,用于明确组件类型,便于 Spring 扫描和后续扩展(如@Repository
自动转换数据库异常)。
@Configuration
和@Bean
的作用?与 XML 配置相比有何优势?
@Configuration
:标识配置类(替代 XML 配置文件)。@Bean
:在配置类中定义 Bean(替代 XML 中的<bean>
标签),方法名默认作为 Bean 名称,返回值作为 Bean 实例。- 优势:类型安全(编译期检查)、支持 Java 代码逻辑(如条件判断创建不同 Bean)、更简洁。
@Scope
注解的作用?如何实现一个线程安全的singleton
Bean?
@Scope
:指定 Bean 的作用域(如@Scope("prototype")
)。- 线程安全
singleton
实现:
- 避免 Bean 存储状态(无成员变量,或成员变量是不可变的
final
类型)。- 用
ThreadLocal
存储线程私有状态(如RequestContextHolder
)。- 对状态修改加锁(如
synchronized
或Lock
)。
五、Spring MVC 与 Web 相关
- Spring MVC 的工作流程?
- 客户端发送请求 → 前端控制器
DispatcherServlet
接收。DispatcherServlet
调用HandlerMapping
找到对应Handler
(控制器方法)。- 调用
HandlerAdapter
执行Handler
(适配不同的控制器类型,如注解式、接口式)。Handler
执行完成返回ModelAndView
(数据和视图名)。DispatcherServlet
调用ViewResolver
解析视图名,生成View
对象。View
渲染数据 → 响应客户端。
@RequestMapping
注解的作用?@GetMapping
、@PostMapping
与它的关系?
@RequestMapping
:映射请求路径和方法(支持value
、method
、params
、headers
等属性,如method = RequestMethod.GET
限制 GET 请求)。@GetMapping
是@RequestMapping(method = RequestMethod.GET)
的缩写,@PostMapping
同理,简化 RESTful 接口开发。
- Spring MVC 如何接收请求参数?
- 基本类型/包装类:直接在控制器方法参数中声明(如
public String getUser(int id)
)。- 对象:参数名与对象属性名匹配,自动封装(如
public String saveUser(User user)
)。- 路径变量:
@PathVariable
(如@GetMapping("/user/{id}")
对应int id
)。- 请求体:
@RequestBody
(接收 JSON 数据,自动转为对象)。- 表单/查询参数:
@RequestParam
(指定参数名,支持required
、defaultValue
)。
六、Spring Boot 相关
- Spring Boot 的核心特性?与 Spring 的区别?
- 核心特性:基于
约定优于配置
的思想,自动配置(@EnableAutoConfiguration
)、起步依赖(starter
,简化依赖管理)、嵌入式服务器(如 Tomcat,无需单独部署)、Actuator(监控应用)、简化配置(application.yml
替代 XML)。- 区别:Spring 是基础框架,需手动配置大量 XML 或注解;Spring Boot 是 Spring 的“脚手架”,通过自动配置和起步依赖简化开发,本质是 Spring 的扩展。
- Spring Boot 的自动配置原理?
- 核心是
@EnableAutoConfiguration
注解,通过@Import(AutoConfigurationImportSelector.class)
加载META-INF/spring.factories
中定义的自动配置类(如DataSourceAutoConfiguration
)。- 自动配置类通过
@Conditional
注解(如@ConditionalOnClass
、@ConditionalOnMissingBean
)判断是否生效,若满足条件则创建默认 Bean(如未手动配置数据源时,自动配置默认数据源)。
- 如何自定义 Spring Boot Starter?
- 步骤:
- 创建 Maven 项目,定义起步依赖(引入核心库和自动配置类依赖)。
- 编写自动配置类(
@Configuration
+@Bean
定义默认组件)。- 在
src/main/resources/META-INF/spring.factories
中注册自动配置类(org.springframework.boot.autoconfigure.EnableAutoConfiguration=xxx.MyAutoConfiguration
)。
总结
Spring 面试重点考察 IOC/DI 原理、AOP 实现与应用、事务管理机制、核心注解使用 及 Spring MVC 工作流程。回答时需结合底层实现(如动态代理、Bean 生命周期)和实战经验(如事务失效场景、 Starter 自定义),体现对框架设计思想的理解。