本附录梳理了 Java Spring 相关面试中最常出现的问题,涵盖核心容器、AOP、事务、Spring Boot、Spring MVC 以及微服务等方向。每个题目附有简要答案与考点分析,帮助你在理解的基础上抓住回答要领。
C.1 控制反转与依赖注入
Q1:什么是控制反转(IoC)?Spring 是如何实现 IoC 的?
参考答案:
控制反转是一种设计原则,将对象的创建、依赖管理和生命周期的控制权从应用程序代码转移给外部容器。在 Spring 中,这个容器就是 IoC 容器(ApplicationContext)。它通过读取配置(XML、注解或 Java Config)获取 Bean 的定义,利用反射创建对象并完成依赖注入,从而将各个组件松散地装配在一起。开发者只需声明依赖,不需要干涉对象的构造过程。
核心考点: IoC 的概念本质、IoC 与 DI 的关系、Spring 容器的角色。
Q2:Spring 中有哪些依赖注入方式?你推荐哪种?为什么?
参考答案:
三种:构造器注入、Setter 注入和字段注入(@Autowired 加在字段上)。
- 构造器注入:依赖由构造函数传入,对象创建后即可用,不可变,强制依赖清晰,易于测试,是官方推荐的方式。
- Setter 注入:适用于可选依赖或需要后续修改的场景,但对象可能处于不完整状态。
- 字段注入:代码简洁,但隐藏了依赖关系,难以测试(需要反射注入),不符合面向对象封装原则,实际项目中应谨慎使用。
核心考点: 三种注入的区别、优缺点、实际选型依据。
C.2 Bean 生命周期与作用域
Q3:描述 Spring Bean 的生命周期。
参考答案:
大致流程:
- 实例化:容器根据 Bean 定义通过反射创建对象实例。
- 属性填充:注入依赖的属性值。
- Aware 回调:如果 Bean 实现了
BeanNameAware、BeanFactoryAware、ApplicationContextAware等接口,依次回调。 - 前置处理:遍历
BeanPostProcessor的postProcessBeforeInitialization方法。 - 初始化:若实现了
InitializingBean则调用afterPropertiesSet();若指定了init-method则调用该方法。 - 后置处理:遍历
BeanPostProcessor的postProcessAfterInitialization(这里是 AOP 代理生成的关键时机)。 - Bean 就绪:可以正常使用。
- 销毁:容器关闭时,若实现
DisposableBean则调用destroy(),或调用指定的destroy-method。
核心考点: 全生命周期的关键节点,尤其是 BeanPostProcessor 的作用(AOP 基于此)。
Q4:Spring 中 Bean 的作用域有哪些?prototype 与 singleton 区别?
参考答案:
- singleton(默认):整个容器中仅一个实例,所有请求共享。适合无状态服务。
- prototype:每次获取都创建新实例。适合有状态对象。
- request / session / application / websocket:仅 Web 环境有效,分别绑定到 HTTP 请求、会话、ServletContext、WebSocket 生命周期。
区别:singleton 生命周期由容器完全管理,prototype 在创建后容器不再负责销毁(需客户端自行释放资源)。若 singleton 依赖 prototype,单例内的 prototype 只会注入一次,需使用 ObjectFactory 或 @Lookup 动态获取。
核心考点: 作用域适用场景、prototype 的陷阱。
C.3 面向切面编程
Q5:什么是 AOP?它解决了什么问题?
参考答案:
AOP(Aspect-Oriented Programming)通过将横切关注点(如日志、事务、安全)从业务逻辑中分离出来,封装成切面,在运行时动态织入目标方法,实现代码复用和核心业务的纯净性。它解决了传统 OOP 中代码散乱和模块纠缠的问题,大幅提升可维护性。
核心考点: AOP 的设计初衷、与 OOP 的互补关系。
Q6:Spring AOP 的底层实现原理?它与 AspectJ 的区别?
参考答案:
Spring AOP 基于动态代理:
- 若目标对象实现了接口,使用 JDK 动态代理(
java.lang.reflect.Proxy)。 - 若没有实现接口,使用 CGLIB 动态字节码生成子类代理。
与 AspectJ 的区别:
- Spring AOP 是运行时织入,只支持方法级别的拦截,性能略低但使用简单,是 Spring 集成的一部分。
- AspectJ 提供编译时、类加载时织入,功能更强大(可拦截字段、构造函数等),需额外的编译器或织入工具,但性能更好。
核心考点: 动态代理的选择策略、两者的适用场景。
C.4 事务管理
Q7:Spring 的声明式事务是如何实现的?@Transactional 失效的场景有哪些?
参考答案:
声明式事务基于 AOP 实现。容器为标注 @Transactional 的类生成代理,在方法前后执行事务开启、提交或回滚。
常见失效场景:
- 方法非 public:Spring AOP 默认只代理 public 方法。
- 自调用:类内部通过
this.method()调用,不经过代理对象,事务不生效(需通过AopContext.currentProxy()或注入自身)。 - 异常被捕获:若在方法内捕获取消了异常,事务不会回滚;默认只回滚
RuntimeException和Error。 - 数据库引擎不支持:如 MyISAM 不支持事务。
- 事务传播行为设置错误:例如
Propagation.NOT_SUPPORTED会挂起当前事务。 - 类未托管:调用的是非 Spring Bean 的方法。
核心考点: AOP 代理的原理、事务失效的排查思路。
Q8:Spring 的事务传播行为有哪些?举例说明 REQUIRED 和 REQUIRES_NEW 的区别。
参考答案:
七种传播行为:
- REQUIRED(默认):当前有事务则加入,无则新建。
- REQUIRES_NEW:始终新建事务,挂起当前事务。
- SUPPORTS:有则加入,无则非事务执行。
- NOT_SUPPORTED:非事务执行,挂起当前事务。
- MANDATORY:必须在事务中运行,否则抛异常。
- NEVER:不能在事务中运行,否则抛异常。
- NESTED:嵌套事务,内层事务可单独回滚,外层不影响。
区别举例:转账操作中调用记录日志。若日志使用REQUIRES_NEW,即使转账回滚,日志也已提交;若用REQUIRED,日志将与转账同事务一起回滚。
核心考点: 传播行为的适用场景,尤其是 REQUIRED 和 REQUIRES_NEW 的业务影响。
C.5 Spring Boot 基础
Q9:Spring Boot 的自动配置原理是什么?
参考答案:
@SpringBootApplication包含@EnableAutoConfiguration,该注解通过@Import导入AutoConfigurationImportSelector。- 该类读取
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(或较早版本的spring.factories)中列出的自动配置类全限定名。 - 每个自动配置类通过
@ConditionalOnClass、@ConditionalOnMissingBean等条件注解判断是否生效。 - 匹配成功则自动创建并注册 Bean(如数据源、Web 服务器等),实现一键集成。
核心考点: @EnableAutoConfiguration 机制、条件注解的运用。
Q10:如何自定义 Starter?关键步骤是什么?
参考答案:
- 创建
autoconfigure模块,撰写自动配置类(@Configuration+ 条件注解)。 - 在
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports中添加配置类路径。 - 编写
spring-boot-starter-xxx模块,仅引入autoconfigure模块及必要三方依赖。 - (可选)提供
application.properties前缀属性,使用@ConfigurationProperties接收参数,并在配置类中启用@EnableConfigurationProperties。
核心考点: Starter 的结构、自动配置脚本的注册位置。
C.6 Spring MVC
Q11:描述 Spring MVC 的请求处理流程。
参考答案:
- 请求到达前端控制器
DispatcherServlet。 DispatcherServlet调用HandlerMapping获取匹配的HandlerExecutionChain(包含拦截器和处理器)。- 通过
HandlerAdapter执行具体的处理器(Controller)。 - 处理器返回
ModelAndView(或通过@ResponseBody直接写回数据)。 - 视图解析器
ViewResolver解析逻辑视图名为具体视图(JSP、Thymeleaf 等)。 - 渲染视图并返回响应。
核心考点: 前端控制器模式、各组件的职责。
Q12:@RestController 与 @Controller 的区别?
参考答案:
@Controller用于定义控制器,方法返回值通常是视图名(配合@ResponseBody可返回 JSON)。@RestController是@Controller+@ResponseBody的合体,类中所有方法都直接返回 JSON/XML 等数据,适合 REST API。
核心考点: REST 风格与视图渲染的区分。
C.7 Spring Security
Q13:Spring Security 的过滤器链是如何工作的?简述认证流程。
参考答案:
Spring Security 基于 FilterChainProxy 管理一系列安全过滤器(如 UsernamePasswordAuthenticationFilter、BearerTokenAuthenticationFilter)。认证流程(以表单登录为例):
- 用户提交用户名密码,
UsernamePasswordAuthenticationFilter将其封装为UsernamePasswordAuthenticationToken。 - 调用
AuthenticationManager(核心接口),其实现ProviderManager委托给一组AuthenticationProvider。 - 例如
DaoAuthenticationProvider通过UserDetailsService加载用户信息,比对密码。 - 认证通过后,将包含权限的
Authentication对象存入SecurityContextHolder(默认ThreadLocal)。
核心考点: 过滤器链结构、认证核心接口。
C.8 微服务与 Spring Cloud
Q14:Spring Cloud 的核心组件及其功能?
参考答案:
- 服务发现:Eureka、Consul、Nacos,负责服务注册与发现。
- 配置中心:Spring Cloud Config、Nacos,集中管理配置并支持动态刷新。
- 负载均衡:Spring Cloud LoadBalancer(先前的 Ribbon),客户端负载均衡。
- 远程调用:OpenFeign,声明式 HTTP 客户端。
- 断路器:Resilience4j / Sentinel,防止级联故障。
- 网关:Spring Cloud Gateway,统一入口、路由、过滤。
- 消息总线:Spring Cloud Bus,配合 Config 实现广播配置变更。
- 流式消息:Spring Cloud Stream,屏蔽底层 MQ 差异。
核心考点: 组件体系的整体理解,不要只记名词而要懂用途。
Q15:如何理解服务雪崩?Sentinel 或 Resilience4j 如何解决?
参考答案:
服务雪崩:微服务链路上一个服务不可用,导致故障沿依赖链向上蔓延,最终整个系统瘫痪。
解决思路:
- 熔断:当失败率达到阈值时,快速失败,不再调用故障服务。
- 降级:提供 fallback 逻辑,返回默认值或友好提示。
- 隔离:线程池或信号量隔离,限制对单个服务的资源占用。
- 限流:控制 QPS,避免过载。
核心考点: 高可用治理的核心理念,能结合工具说明实现机制。
以上问题覆盖了 Spring 面试的主线考点。真正面试时,考官往往会刨根问底,建议结合本书相关章节深入理解原理,而非死记硬背。掌握这些骨架,再填充项目中的真实案例,面试通过率将大幅提升。