这次我们来看一个针对 Spring 技术栈的面试题集锦项目。对于 Java 开发者来说,Spring 框架是面试中绕不开的核心,从基础的 IOC、AOP 到 Spring Boot、Spring Cloud,再到新兴的 Spring AI,知识点繁杂且深度要求高。这个项目将高频面试题进行了系统性的梳理,覆盖了从核心原理到微服务、AI 集成的全链路,目标是帮助开发者高效备战,在面试中“赢麻了”。

本文的核心不是教你 Spring 框架本身,而是帮你快速掌握如何利用这份面试题集进行高效复习。我们会拆解这份资料的结构,提炼每个模块的核心考点,并提供一套可执行的复习和验证方法。无论你是准备校招、社招,还是想系统性巩固 Spring 生态,这篇文章都能提供直接的路径。

1. 核心能力速览

这份面试题集更像是一份精心编排的“知识地图”和“模拟题库”,其核心价值在于覆盖的广度和对重点的把握。

能力项 说明
覆盖范围 全面覆盖 Spring 核心 (IOC/AOP/Bean)、Spring Boot、Spring Cloud、Spring AI 等主流技术栈。
题目数量 70+ 道精选高频面试题,质量优于网络零散资料。
内容深度 从概念、原理到源码、实战配置,兼顾基础与深度。
学习目标 用于面试突击、知识查漏补缺、构建系统性知识框架。
使用方式 自主阅读、理解记忆、模拟自测、结合源码验证。
输出成果 提升面试通过率,深入理解 Spring 生态工作原理。

2. 适用场景与使用边界

这份资料主要服务于以下几类开发者:

  1. 求职面试者 :正在准备 Java 后端开发岗位面试,需要快速梳理 Spring 相关知识点,应对技术面。
  2. 技能提升者 :已经会使用 Spring 进行开发,但对其底层原理、设计思想理解不深,希望通过问题驱动的方式加深理解。
  3. 知识体系构建者 :感觉 Spring 知识碎片化,希望有一份提纲挈领的资料,帮助自己建立完整的知识树。
  4. 技术面试官 :可以作为题库参考,用于考察候选人对 Spring 生态的掌握程度。

使用边界与注意事项:

  • 非教程或源码 :这不是一份 Spring 框架的入门教程,也不是完整的源代码分析。它是一份问题清单,答案需要你结合官方文档、书籍和源码自行探索或参考资料中的解析。
  • 时效性 :Spring 生态迭代迅速(如 Spring Boot 3.x 与 2.x 的差异,Spring AI 的快速更新),使用时应关注题目对应的 Spring 版本,并对新特性保持敏感。
  • 理解重于背诵 :面试官更关注你对原理的理解和解决问题的思路,而非死记硬背答案。建议对每个问题,都能用自己的话阐述,并能举出简单的代码示例。

3. 环境准备与前置条件

要最大化利用这份面试题集,特别是进行原理验证和代码实践,你需要准备好相应的开发和学习环境。

  1. 基础 Java 开发环境

    • JDK :建议 JDK 11 或 17(Spring Boot 2.x/3.x 的推荐版本)。
    • IDE :IntelliJ IDEA 或 Eclipse,具备良好的 Spring 支持。
    • 构建工具 :Maven 或 Gradle。
  2. Spring 项目实践环境

    • 最好有一个自己熟悉的 Spring Boot 项目,用于验证 IOC 容器、AOP 切面、Bean 生命周期等概念。
    • 可以准备一个简单的微服务 demo 项目,用于理解 Spring Cloud 组件(如 Nacos, Gateway, OpenFeign)的工作方式。
  3. 源码阅读环境

    • 在 IDE 中下载或关联 Spring Framework、Spring Boot 的源码。这是深入理解“三级缓存”、“自动装配”等问题的关键。
    • 学会使用 IDE 的调试功能,跟踪 Bean 的创建、依赖注入、AOP 代理生成等过程。
  4. 知识检索工具

    • Spring 官方文档( spring.io )是最权威的参考。
    • 准备好用于搜索和扩展学习的浏览器或资料库。

4. 资料结构与核心模块拆解

根据标题“SpringIOC+AOP+Springboot+springcloud+spring AI+Bean”,我们可以将 70+ 问题大致划分为以下几个核心模块。每个模块都对应着面试中的一类重点考察方向。

4.1 Spring Core (IOC, AOP, Bean)

这是 Spring 的基石,面试必考。题目会深入到原理和源码层面。

核心考点预测:

  • IOC (控制反转) & DI (依赖注入) :概念、好处、实现原理。
  • Bean 生命周期 :从定义到销毁的完整过程(InstantiationAwareBeanPostProcessor, BeanPostProcessor 等接口的作用)。
  • Bean 作用域 :singleton, prototype, request, session 等,以及它们的实现差异。
  • 循环依赖 :Spring 如何解决循环依赖?三级缓存(singletonFactories, earlySingletonObjects, singletonObjects)的详细工作流程。
  • AOP (面向切面编程) :概念、应用场景(日志、事务、权限等)。
  • AOP 实现原理 :JDK 动态代理 vs CGLIB 代理的区别、选择依据及原理。
  • 事务管理 :声明式事务原理(@Transactional)、传播行为、隔离级别。

学习验证方法:

  1. 创建一个 Spring Boot 项目,定义两个相互依赖的 Bean,模拟循环依赖,通过调试模式观察三级缓存的变化。
  2. 编写一个自定义的 BeanPostProcessor ,在 Bean 初始化前后打印日志,理解其执行时机。
  3. 分别创建基于接口和基于类的 Bean,配置 AOP 切面,查看生成的代理对象类型(JDK Proxy 或 CGLIB)。

4.2 Spring Boot

Spring Boot 是现代 Spring 开发的起点,考察重点在自动装配和简化配置。

核心考点预测:

  • 自动装配原理 @SpringBootApplication 注解的组成、 @EnableAutoConfiguration 的作用、 spring.factories 文件机制(Spring Boot 2.7+ 已迁移到 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports )。
  • 启动流程 :SpringApplication.run() 方法执行的主要阶段。
  • 外部化配置 application.properties / yml 的加载顺序、自定义配置类、多环境配置。
  • Starter 机制 :自定义 Starter 的编写。
  • 内嵌容器 :Tomcat 替换为其他容器(如 Jetty, Undertow)或国产中间件(如标题提到的“宝蓝德”)的方法与原理。

学习验证方法:

  1. 查看 spring-boot-autoconfigure 包下的 META-INF 目录,理解自动配置列表。
  2. 编写一个简单的自定义 Starter,包含自动配置类和 spring.factories (或 .imports 文件)配置。
  3. application.yml 中配置不同环境的属性,并通过 @ConfigurationProperties 绑定到 Java 对象。

4.3 Spring Cloud

微服务架构的核心,考察对主流组件原理和应用的掌握。

核心考点预测:

  • 五大组件 :Eureka/Nacos(服务发现)、Ribbon/LoadBalancer(负载均衡)、Feign/OpenFeign(声明式HTTP客户端)、Hystrix/Sentinel(熔断降级)、Zuul/Gateway(网关)。需理解其各自职责。
  • 服务注册与发现 :工作流程、健康检查、CAP 理论下的选择(Eureka AP, Nacos 支持 AP/CP)。
  • 服务调用 :OpenFeign 的原理、如何集成负载均衡器、超时与重试配置。
  • 网关 Gateway :路由、断言、过滤器的使用与自定义、如何访问下游微服务。
  • 配置中心 :Spring Cloud Config 或 Nacos Config 的使用。
  • 分布式事务 :Seata 等方案的了解。

学习验证方法:

  1. 使用 Nacos 作为注册中心,搭建两个简单的微服务 Provider 和 Consumer,实现服务注册、发现与调用。
  2. 配置 Spring Cloud Gateway,定义路由规则将请求转发到上述微服务。
  3. 在 Consumer 中使用 @FeignClient 调用 Provider,并配置熔断规则(如使用 Sentinel)。

4.4 Spring AI

这是新兴且增长迅速的方向,考察对 Spring 生态整合 AI 能力的了解。

核心考点预测:

  • 核心概念 :Spring AI 项目的目的、核心抽象(如 ChatClient , EmbeddingClient , VectorStore )。
  • 快速入门 :如何引入 Spring AI 依赖,配置 OpenAI、Azure OpenAI 或 Ollama(本地模型)等后端。
  • 本地 Vector Store :如何使用 Spring AI 集成 Chroma、PgVector 等,搭建本地知识库(如标题提到的 spring ai 1.1.0 .快速使用 本地 vector store )。
  • 知识库搭建 :RAG(检索增强生成)的基本流程在 Spring AI 中的实现。
  • 与 Alibaba 等云厂商的整合

学习验证方法:

  1. 创建一个新项目,引入 spring-ai-openai-spring-boot-starter 依赖,配置 API Key,编写一个简单的聊天对话接口。
  2. (进阶)尝试集成 spring-ai-chroma spring-ai-pgvector ,将本地文档切片、向量化并存储,实现一个简单的基于文档问答的端点。

4.5 综合与实战

这部分问题可能横跨多个模块,或涉及具体实战场景。

核心考点预测:

  • Spring 事务在 Spring Boot 中的行为 :自动提交? @Transactional 失效场景。
  • Spring Boot 项目实战 :项目结构规划、整合 MyBatis/PageHelper、整合消息队列(如 ActiveMQ)、多数据源配置、Docker 部署。
  • 问题排查 :如“yml 图标红色 = ide 没有识别成 spring 配置文件”这类 IDE 或配置问题。
  • 源码手写 :“手写 Spring”类题目,考察对 IOC 容器最简单实现的理解。
  • 版本对比 :Spring Boot 2.x 与 3.x 的主要区别。

5. 高效复习与自测工作流

拿到 70+ 道题目,盲目刷题效率低下。建议遵循以下工作流:

第一步:模块化分类与评估 将题目按照上述 4.1-4.5 的模块进行分类。快速浏览所有题目,对自己熟悉的模块和生疏的模块有一个整体评估。

第二步:建立知识锚点与深度探索 针对每个模块,特别是生疏部分:

  1. 概念澄清 :对于每个问题,先尝试自己回答。卡住的地方,就是知识盲点。
  2. 官方文档溯源 :针对盲点,去 Spring 官方文档查找最权威的定义和说明。
  3. 源码佐证 :对于原理性问题(如三级缓存、自动装配),务必在 IDE 中打开源码,通过调试或阅读,理清关键流程。可以画简单的时序图或流程图帮助理解。
  4. 代码验证 :对于涉及配置、使用的问题(如 AOP 使用、Gateway 配置),创建一个最简单的 Demo 项目进行验证,确保“手熟”。

第三步:模拟面试与输出训练

  1. 自言自语 :针对一个问题,假设自己在面试,用清晰、有条理的语言将答案说出来。关注表达的逻辑性(是什么-为什么-怎么做)。
  2. 白板编码 :对于“手写 Spring 核心”、“实现一个简单 AOP”等题目,尝试在纸上或白板上写出核心代码结构。
  3. 关联思考 :面试官常会追问。例如,回答完“JDK 动态代理和 CGLIB 区别”后,要能联想到“Spring 如何选择”、“什么情况下会强制使用 CGLIB”。

第四步:错题整理与迭代 将理解不透彻、表达不清晰的问题记录下来,形成自己的“错题本”。定期回顾,并重复第二步的深度探索过程。

6. 重点难题与原理剖析示例

这里选取几个典型的高频难题,展示如何深入分析和验证。

6.1 Spring 如何解决循环依赖?(三级缓存原理)

这是 Spring 源码的经典问题。不能只背“三级缓存”这个名字,要理解其过程。

分析流程:

  1. 场景 :Bean A 依赖 Bean B,Bean B 依赖 Bean A。
  2. 缓存介绍
    • singletonObjects (一级缓存):存放完整的单例 Bean。
    • earlySingletonObjects (二级缓存):存放早期的 Bean 引用(已实例化,但未完成属性填充和初始化)。
    • singletonFactories (三级缓存):存放 Bean 工厂对象,用于创建早期引用。
  3. 解决步骤
    1. 开始创建 A,实例化 A(调用构造器),将 A 的工厂对象放入 三级缓存
    2. 为 A 填充属性,发现需要 B,于是去获取 B。
    3. 开始创建 B,实例化 B,将 B 的工厂对象放入 三级缓存
    4. 为 B 填充属性,发现需要 A,于是去获取 A。
    5. 一级缓存 未找到 A,从 二级缓存 未找到 A,但从 三级缓存 找到了 A 的工厂对象。
    6. 通过工厂对象获取 A 的早期引用(可能是 AOP 代理对象),并将此引用放入 二级缓存 ,同时 删除三级缓存 中的 A 工厂。
    7. B 成功获得 A 的早期引用,完成属性填充和初始化,成为一个完整的 Bean,放入 一级缓存 ,并清理二、三级缓存。
    8. 流程回到 A,此时能成功从 一级缓存 获取到完整的 B,A 完成属性填充和初始化,放入 一级缓存
  4. 关键点 :三级缓存的核心价值在于处理 存在 AOP 代理 时的循环依赖。工厂可以提前返回代理对象。

验证方法: 在自定义 Bean 的构造器、 @PostConstruct 方法中打印日志,并通过 DefaultSingletonBeanRegistry 源码设置断点,观察三个 Map 的变化。

6.2 Spring Boot 自动装配原理

分析流程:

  1. 入口 @SpringBootApplication 是一个组合注解,包含 @EnableAutoConfiguration
  2. @EnableAutoConfiguration :通过 @Import(AutoConfigurationImportSelector.class) 导入选择器。
  3. AutoConfigurationImportSelector :其 selectImports 方法会调用 getAutoConfigurationEntry ,核心是 SpringFactoriesLoader.loadFactoryNames
  4. 加载配置 :从所有 jar 包的 META-INF/spring.factories (旧)或 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports (新)文件中,读取 EnableAutoConfiguration 对应的全限定类名。
  5. 过滤 :加载的配置类会经过 @ConditionalOnClass , @ConditionalOnMissingBean 等条件注解的过滤,最终生效的配置类才会被真正注册到容器中。

验证方法:

  1. 查看 spring-boot-autoconfigure jar 包中的 /META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件。
  2. 创建一个项目,引入 spring-boot-starter-web ,在启动类上 @SpringBootApplication 处打断点,调试进入 AutoConfigurationImportSelector ,查看 getCandidateConfigurations 方法返回的列表。

6.3 Spring AOP 中 JDK 动态代理与 CGLIB 代理的区别

对比分析:

特性 JDK 动态代理 CGLIB 代理
原理 基于接口,使用 Proxy InvocationHandler 创建代理类。 基于继承,通过字节码技术生成目标类的子类作为代理类。
目标要求 目标类必须实现至少一个接口。 目标类不能是 final 的。
性能 生成代理较快,调用稍慢(反射调用)。 生成代理较慢(需操作字节码),调用较快(直接方法调用)。
依赖 JDK 原生支持,无需额外库。 需要引入 cglib 库(Spring 核心包已包含)。
代理对象 实现与目标类相同的接口。 是目标类的子类。

Spring 的选择策略:

  1. 如果目标对象实现了接口,默认使用 JDK 动态代理。
  2. 如果目标对象没有实现接口,则使用 CGLIB。
  3. 可以通过配置 spring.aop.proxy-target-class=true 强制使用 CGLIB 代理(即使有接口)。

验证方法:

// 定义一个接口和一个实现类
public interface UserService { void save(); }
@Component
public class UserServiceImpl implements UserService {
    @Override
    public void save() { System.out.println("save user..."); }
}

// 定义一个切面
@Aspect
@Component
public class LogAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void beforeLog() { System.out.println("before log..."); }
}

// 在测试类中获取并打印 Bean 的类型
@SpringBootTest
class TestProxy {
    @Autowired
    private UserService userService; // 这里注入的是代理对象

    @Test
    void testProxyType() {
        System.out.println(userService.getClass());
        // 输出可能为:class com.sun.proxy.$ProxyXXX (JDK Proxy)
        // 如果设置了 proxy-target-class=true,输出可能为:class com.example.service.UserServiceImpl$$EnhancerBySpringCGLIB$$...
    }
}

7. 实战场景与配置要点

结合网络热词中的具体场景,这里给出一些实战配置的要点。

7.1 Spring Boot 整合 MyBatis PageHelper

这是一个非常常见的需求,用于数据库分页。

关键步骤:

  1. 添加依赖 mybatis-spring-boot-starter pagehelper-spring-boot-starter
  2. 配置参数 :在 application.yml 中配置 PageHelper 属性,如方言、合理化等。
    pagehelper:
      helper-dialect: mysql
      reasonable: true
      support-methods-arguments: true
    
  3. 使用 :在 Service 层,在查询方法 调用 PageHelper.startPage(pageNum, pageSize) ,后续的第一个 MyBatis 查询会自动进行物理分页。

7.2 Spring Cloud Gateway 访问微服务

核心配置:

spring:
  cloud:
    gateway:
      routes:
        - id: user-service-route
          uri: lb://user-service # lb:// 表示从注册中心负载均衡
          predicates:
            - Path=/api/user/**
          filters:
            - StripPrefix=1 # 去掉路径前缀 /api
  • uri: lb://service-name 是关键,Gateway 会从注册中心(如 Nacos)发现名为 user-service 的服务实例列表,并进行负载均衡。
  • Predicate 定义匹配规则。
  • Filter 可以对请求/响应进行处理, StripPrefix 是常用过滤器,用于去掉网关路径前缀。

7.3 Spring AI 快速使用本地 Vector Store

以 Chroma 为例(需本地启动 Chroma 服务):

  1. 添加依赖
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-chroma-store-spring-boot-starter</artifactId>
    </dependency>
    
  2. 配置连接
    spring:
      ai:
        vectorstore:
          chroma:
            embedding-dimension: 384 # 与使用的 Embedding 模型维度一致
            host: localhost
            port: 8000
    
  3. 使用 :注入 VectorStore 接口,调用 add , similaritySearch 等方法进行文档的存储和检索。

8. 常见问题与排查方法

在学习和面试准备过程中,会遇到各种问题。下表列出一些常见问题及解决思路。

问题现象 可能原因 排查方式 解决方案
@Autowired 注入失败,Bean 找不到 1. Bean 未被扫描到(不在启动类同级或子包下)。
2. 没有 @Component 或其衍生注解。
3. 存在多个同类型 Bean,未使用 @Qualifier
1. 检查包结构。
2. 检查类注解。
3. 查看启动日志中的 Bean 定义。
1. 使用 @ComponentScan 指定包。
2. 添加正确的注解。
3. 使用 @Primary @Qualifier
@Transactional 事务不生效 1. 方法非 public
2. 异常被捕获未抛出。
3. 数据库引擎不支持事务(如 MyISAM)。
4. 自调用问题(类内部方法调用)。
1. 检查方法修饰符。
2. 检查 try-catch。
3. 检查数据库引擎。
4. 检查调用方式。
1. 将方法改为 public
2. 在 catch 中抛出 RuntimeException
3. 切换为 InnoDB。
4. 通过代理对象调用(如从容器获取 Bean)。
Spring Boot 配置文件不生效(如 yml 图标红色) 1. 文件命名不正确。
2. 文件位置不对。
3. IDE 未识别为 Spring 配置文件。
1. 确认是 application.yml application.properties
2. 确认文件在 src/main/resources 下。
3. 检查 IDE 的 Spring 插件是否启用。
1. 更正文件名。
2. 移动文件到正确目录。
3. 在 IDE 中右键文件,选择“Spring Boot” -> “Add as Spring Boot Config File”。
Feign 调用超时或失败 1. 服务提供者未注册或宕机。
2. 网络问题。
3. Feign/ Ribbon 超时时间设置过短。
1. 检查注册中心服务列表。
2. 使用 curl 或 Postman 直接测试提供者接口。
3. 查看 Feign 和 Ribbon 配置。
1. 确保提供者健康并已注册。
2. 调整 Feign 和 Ribbon 的超时配置。
3. 启用熔断器进行容错。
自动配置类未生效 1. 依赖未引入。
2. 条件注解不满足(如缺少某个类)。
3. 自定义配置覆盖了默认配置。
1. 检查 pom.xml build.gradle
2. 开启 Debug 日志 ( debug=true ),查看自动配置报告。
3. 检查是否有自定义的 @Bean 定义了相同类型。
1. 添加正确的 Starter 依赖。
2. 根据报告补充依赖或排除冲突。
3. 检查自定义配置,使用 @ConditionalOnMissingBean 等注解。

9. 最佳实践与复习建议

  1. 由浅入深,建立体系 :不要一开始就扎进源码。先理解核心概念(IOC, AOP, Bean),再学习高级特性(事务、缓存),最后结合 Spring Boot/Cloud 进行应用和源码探究。
  2. 动手实践,加深记忆 :对于每个重要知识点,尽量编写一个小 Demo 来验证。例如,理解 Bean 生命周期,就自己实现一个 BeanPostProcessor
  3. 善用官方文档和源码 :官方文档是标准答案,源码是终极解释。遇到模糊的概念,第一时间查阅文档;遇到复杂的流程,通过调试源码理清脉络。
  4. 模拟面试,输出倒逼输入 :定期进行模拟自测,尝试口头回答题目。录音回听,检查自己的表达是否清晰、逻辑是否连贯。这能极大暴露理解薄弱点。
  5. 关注社区与版本更新 :Spring 生态活跃,关注 Spring 官方博客、Release Notes,了解新特性和最佳实践的变化(如 Spring Boot 2.x 到 3.x 的迁移,配置文件的变更)。
  6. 构建知识连接网 :将分散的知识点连接起来。例如,谈到 AOP,要能联想到事务 @Transactional 就是基于 AOP 实现的;谈到 Spring Boot 启动,要能联系到 Spring 容器的刷新过程。

这份“一口气吃透 Spring 框架面试 70 问”资料是一个极佳的引子和地图。它帮你划定了重点,指明了方向。真正的“吃透”,需要你沿着它指出的每条路径,用自己的思考和实践去走一遍。结合本文提供的模块拆解、原理剖析、实战验证和排查方法,你可以将它从一份静态的题库,转化为动态的、属于你自己的 Spring 技术认知体系。接下来,就从你最不熟悉的那部分题目开始,启动你的 IDE,开始验证之旅吧。

更多推荐