Spring面试题宝典:核心原理与高频考点深度剖析(2025持续更新版)

【导读】 本文并非简单的面试题罗列,而是致力于构建一座从Spring基础到高级特性的知识大厦。我们不仅提供“是什么”的答案,更深入挖掘“为什么”和“怎么办”,结合底层原理和实战经验,助你彻底征服Spring面试,斩获心仪Offer!

📖 一、Spring基石篇:IoC与DI深度解密

1.1 谈谈你对Spring框架的理解?

参考答案:
Spring是一个轻量级、开源、一站式的Java企业级应用开发框架。其核心使命是简化企业级应用开发,通过提供一套集成化的解决方案,让开发者能更专注于业务逻辑。

核心策略与优势:

  • 控制反转(IoC) / 依赖注入(DI):实现组件间松耦合的基石。
  • 面向切面编程(AOP):将横切关注点(如日志、事务、安全)模块化,提高代码复用性和可维护性。
  • 丰富的生态集成:无缝集成各种优秀框架(如Hibernate, MyBatis)和技术(如缓存、消息队列)。
  • 简化API使用:对JDBC、JavaMail等繁琐的JavaEE API进行了大幅简化。
  • 非侵入式设计:你的POJO类通常不直接依赖于Spring特定类,代码污染极低。

1.2 详细阐述Spring IoC容器的工作机制?

参考答案:
IoC(控制反转)是一种设计思想,将传统由程序代码直接操控的对象调用权交给容器,由容器来管理对象的生命周期和依赖关系。

Spring IoC容器实现机制:工厂模式 + 反射机制 + 策略模式

  1. 加载与解析配置:容器启动时,读取配置文件(XML/Java Config/注解),将每个<bean>@Bean解析为一个BeanDefinition对象,它包含了创建一个Bean的所有元数据。
  2. BeanDefinition注册:将BeanDefinition注册到BeanDefinitionRegistry(一个巨大的Map)中。
  3. Bean实例化:当调用getBean()时,容器根据BeanDefinition中的信息,通过反射机制调用构造方法创建Bean的实例。
  4. 依赖注入:根据配置(构造器注入、Setter注入、自动注入),容器将依赖的其他Bean注入到目标Bean的属性中。
  5. 生命周期回调:如果Bean实现了InitializingBean接口或定义了init-method,容器会调用其初始化方法。
  6. 返回可用对象:此时,一个完整的、依赖关系就绪的Bean就可以被应用程序使用了。

1.3 BeanFactory vs. ApplicationContext,有何区别?

参考答案:

特性BeanFactoryApplicationContext
定位IoC核心基础容器,最底层的接口BeanFactory的超集企业级应用上下文
加载时机懒加载 (Lazy Loading):只有在使用getBean()时才创建和注入Bean预加载 (Eager Loading):容器启动时,就立即创建并配置所有单例Bean
功能提供基础的IoC和DI功能在IoC基础上,提供消息资源处理(i18n)、事件发布、AOP集成、层级上下文、更便捷的资源访问
适用场景资源受限的移动设备或Applet绝大多数J2EE应用,是Spring应用的首选

结论ApplicationContext功能更强大,除非在非常关注内存的场景,否则都应使用它。

1.4 Spring中Bean的作用域有哪些?

参考答案:

  • singleton (默认):每个Spring IoC容器中,一个Bean定义只存在一个共享的实例。
  • prototype:每次请求(调用getBean()或注入时)都会创建一个新的Bean实例。
  • request:一次HTTP请求一个实例(仅适用于Web应用)。
  • session:一个HTTP Session一个实例(仅适用于Web应用)。
  • application:一个ServletContext生命周期一个实例(仅适用于Web应用)。
  • websocket:一个WebSocket生命周期一个实例(仅适用于Web应用)。

1.5 单例Bean是线程安全的吗?如何保证?

参考答案:
Spring框架并不保证单例Bean的线程安全。 线程安全取决于Bean本身的状态(State)

  • 无状态Bean (Stateless Bean):Bean中没有可变的成员变量(只有常量或无状态服务),所有操作都是基于方法参数。这种Bean是线程安全的。例如:Service, Dao等。
  • 有状态Bean (Stateful Bean):Bean中包含可变的成员变量。这种Bean是非线程安全的。

保证线程安全的策略:

  1. 首选:将Bean的作用域改为prototype。每次请求都创建新实例,从根本上避免共享。
  2. 使用ThreadLocal:将有状态的数据存储在ThreadLocal中,为每个线程提供独立的变量副本。
  3. 避免使用实例变量:尽量设计成无状态Bean。
  4. 在方法中加锁 (synchronized):但会严重影响性能,不推荐。

⚔️ 二、AOP核心篇:纵横切面的艺术

2.1 解释一下AOP及其相关术语?

参考答案:
AOP(面向切面编程)是一种编程范式,用于将那些与核心业务逻辑无关,但却被多个模块所共同使用的功能(横切关注点)分离出来,形成可重用的模块。

核心术语:

  • Aspect (切面):横切关注点的模块化。它是AdvicePointcut的集合。通常是一个用@Aspect注解的类。
  • Join Point (连接点):程序执行过程中的一个点,如方法调用、异常抛出。在Spring AOP中,它总是代表一个方法的执行
  • Advice (通知):在特定Join Point上执行的动作。类型有:@Before, @After, @AfterReturning, @AfterThrowing, @Around
  • Pointcut (切点):一个表达式,用于匹配哪些Join Point需要被切入。AdvicePointcut表达式关联。
  • Weaving (织入):将Aspect应用到目标对象并创建代理对象的过程。Spring AOP在运行时完成织入。

2.2 Spring AOP 和 AspectJ 有什么区别?

参考答案:

特性Spring AOPAspectJ
实现方式动态代理(JDK Proxy 或 CGLIB)字节码编辑(编译时、编译后、加载时)
织入时机运行时织入编译期、类加载期织入
性能较好更优(编译后无额外开销)
功能仅支持方法级别的连接点功能全面,支持字段、构造器、静态代码块等连接点
依赖仅需Spring核心包,轻量需要额外的AspectJ编译器和织入器
适用场景Spring管理的Bean,满足大部分企业应用需求需要更强大、更细粒度AOP控制的复杂场景

2.3 JDK动态代理和CGLIB代理如何选择?

参考答案:
Spring AOP自动根据目标类选择代理策略:

  1. JDK Dynamic Proxy (默认策略)
    • 条件:如果目标对象实现了至少一个接口
    • 原理:基于Java反射,在运行时为接口创建一个$Proxy0之类的代理类。
    • 要求:代理类和目标类是实现相同接口的“兄弟”关系。
  2. CGLIB Proxy
    • 条件:如果目标对象没有实现任何接口
    • 原理:通过继承目标类,生成其子类作为代理类,并重写父类方法。
    • 限制:无法代理final类或final方法。

🔄 三、生命周期与高级特性篇

3.1 描述Spring Bean的完整生命周期?

参考答案:
这是一个非常高频的面试题!生命周期大致可分为以下几个阶段:

  1. 实例化 (Instantiate):调用Bean的构造方法,创建一个新的实例。
  2. 属性赋值 (Populate):根据配置(XML, @Autowired等),将依赖的Bean和值注入到属性中。
  3. Aware接口回调:如果Bean实现了各种Aware接口(如BeanNameAware, BeanFactoryAware, ApplicationContextAware),Spring会回调相应方法,将容器信息注入给Bean。
  4. BeanPostProcessor前置处理:调用所有BeanPostProcessorpostProcessBeforeInitialization方法。
  5. 初始化 (Initialization)
    • 执行@PostConstruct注解的方法。
    • 如果实现了InitializingBean接口,执行afterPropertiesSet()方法。
    • 执行自定义的init-method方法。
  6. BeanPostProcessor后置处理:调用所有BeanPostProcessorpostProcessAfterInitialization方法。AOP代理就在此阶段生成!
  7. Bean就绪:此时Bean已完全初始化,存放在单例池中,可供使用。
  8. 销毁 (Destruction)
    • 容器关闭时,执行@PreDestroy注解的方法。
    • 如果实现了DisposableBean接口,执行destroy()方法。
    • 执行自定义的destroy-method方法。

3.2 Spring如何解决循环依赖问题?

参考答案:
循环依赖就是两个或多个Bean相互持有对方的引用,构成一个循环链(如A依赖B,B又依赖A)。

Spring通过三级缓存的机制巧妙地解决了单例Bean通过Setter注入/字段注入造成的循环依赖。

三级缓存:

  1. 一级缓存 (singletonObjects):存放已经完全初始化好的成品Bean
  2. 二级缓存 (earlySingletonObjects):存放半成品Bean(已实例化但未完成属性注入和初始化)。用于从三级缓存中获取经过BeanPostProcessor处理后的早期引用。
  3. 三级缓存 (singletonFactories):存放Bean工厂对象 (ObjectFactory),用于生成Bean的早期引用(一个提前暴露的代理对象)。

解决流程(以A和B循环依赖为例):

  1. 开始创建A,实例化A,将A的工厂对象放入三级缓存
  2. 为A进行属性注入,发现依赖B,于是去创建B。
  3. 开始创建B,实例化B,将B的工厂对象放入三级缓存
  4. 为B进行属性注入,发现依赖A。此时,B从三级缓存中找到A的工厂对象,调用getObject()方法获取A的早期引用(一个代理对象),并将这个早期引用放入二级缓存,同时从三级缓存移除A的工厂。B成功注入A的早期引用,完成初始化,放入一级缓存
  5. A接着注入已完全初始化好的B,完成自己的初始化,放入一级缓存。清理二级缓存。

无法解决的循环依赖:

  • 构造器循环依赖:在实例化阶段就需要依赖,此时Bean甚至还未创建,无法提前暴露引用,Spring直接抛出BeanCurrentlyInCreationException
  • prototype作用域的循环依赖:Spring不缓存prototypeBean,无法暴露早期引用。

3.3 @Autowired 和 @Resource 注解的区别?

参考答案:

特性@Autowired (Spring)@Resource (JSR-250)
提供方Spring框架Java标准注解 (JSR-250)
默认注入方式byTypebyName
注入流程1. 按类型查找Bean
2. 如果找到多个,再按属性名作为Bean Name进行匹配
3. 可通过@Qualifier指定Bean名
1. 按属性名作为Bean Name查找Bean
2. 如果找不到,再回退到byType
required属性有 (@Autowired(required=false))无(找不到就报错)
适用场景推荐在纯Spring项目中使用希望代码与Spring解耦,或需要按名称注入时

💽 四、数据访问与事务篇

4.1 Spring事务管理的原理是什么?

参考答案:
Spring事务的本质是对数据库事务的抽象和封装。其本身并不实现事务,而是提供一套统一的事务管理接口(PlatformTransactionManager),将实际工作委托给底层的持久化框架(如JDBC、Hibernate、JPA)去做。

声明式事务原理:基于AOP动态代理

  1. 在事务方法开始前,通过AOP拦截,调用TransactionInterceptor
  2. 获取事务管理器(PlatformTransactionManager)。
  3. 根据事务属性(@Transactional配置),创建或加入一个事务。
  4. 执行目标方法(你的业务代码)。
  5. 根据执行是否成功(有无异常),提交或回滚事务。

4.2 Spring事务的传播行为有哪些?

参考答案:
传播行为定义了多个事务方法相互调用时,事务应该如何传播

  • PROPAGATION_REQUIRED (默认):如果当前没有事务,就新建一个;如果已存在,就加入它。确保在同一个事务中
  • PROPAGATION_REQUIRES_NEW:无论当前有无事务,都新建一个独立的事务。新事务与原事务无关,独立提交回滚。
  • PROPAGATION_SUPPORTS:支持当前事务。如果当前有事务,就加入;如果没有,就以非事务方式执行。
  • PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作。如果当前有事务,则将其挂起。
  • PROPAGATION_MANDATORY:强制要求必须在已有事务中运行,否则抛出异常。
  • PROPAGATION_NEVER:必须在没有事务的情况下执行,否则抛出异常。
  • PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。嵌套事务是外部事务的子事务,有自己的保存点(savepoint),可以独立回滚。依赖于JDBC 3.0的保存点机制。

4.3 @Transactional注解在什么情况下会失效?

参考答案:
这是一个高级且常见的问题!

  1. 方法非public@Transactional只能用于public方法上。
  2. 自调用问题:同一个类中,一个非事务方法A调用另一个**有@Transactional注解的方法B**,事务会失效。因为代理对象调用的是this.B()`,绕过了代理。
  3. 异常被捕获:默认只在抛出运行时异常(RuntimeException)Error时回滚。如果抛出了检查异常(IOException等)或异常在方法内被try-catch吞掉,事务不会回滚。可通过@Transactional(rollbackFor = Exception.class)配置。
  4. 数据库引擎不支持:例如MySQL的MyISAM引擎不支持事务。
  5. 错误的传播属性:例如配置了PROPAGATION_NOT_SUPPORTED

🌐 五、Spring MVC与Web篇

5.1 描述Spring MVC的核心处理流程?

参考答案:
DispatcherServlet是Spring MVC的核心,是前端控制器模式的实现。

  1. 用户请求:发送请求至前端控制器DispatcherServlet
  2. 查找HandlerDispatcherServlet调用HandlerMapping,根据请求URL找到对应的Handler(通常是ControllerMethod)和HandlerInterceptor
  3. 执行拦截器:执行HandlerInterceptorpreHandle方法。
  4. 适配并执行HandlerDispatcherServlet调用HandlerAdapter去实际执行HandlerHandlerAdapter会处理@RequestMapping、参数绑定等细节。
  5. 处理业务逻辑Controller执行完毕,返回一个ModelAndView对象(包含模型数据和视图名)。
  6. 处理视图DispatcherServlet调用ViewResolver,根据视图名解析出具体的View对象。
  7. 渲染视图View对象结合Model中的数据,进行视图渲染(如填充HTML模板)。
  8. 返回响应:将渲染结果返回给客户端。
  9. 执行拦截器:最后执行HandlerInterceptorpostHandleafterCompletion方法。

5.2 @RestController 和 @Controller 有什么区别?

参考答案:

  • @Controller:标识一个类是Spring MVC的控制器。方法通常返回一个视图名称(String),由ViewResolver解析为物理视图(如JSP, Thymeleaf)。
  • @RestController:是@Controller@ResponseBody组合注解。它标识一个控制器,并且其所有方法都默认添加了@ResponseBody注解,返回值直接写入HTTP响应体(通常转换为JSON/XML),用于构建RESTful Web服务,不返回视图。

🚀 六、Spring Boot与Spring Cloud篇

6.1 Spring Boot的核心优势是什么?

参考答案:
Spring Boot是Spring的脚手架框架,其核心是约定大于配置,旨在快速创建独立、生产级的Spring应用。

  • 自动配置 (Auto-Configuration):根据项目依赖(starter)和类路径,自动配置Spring应用,极大减少XML或Java配置。
  • 内嵌Web容器:内置Tomcat, Jetty或Undertow,无需打包成WAR部署到外部容器,直接打成可执行的JAR包即可运行。
  • 起步依赖 (Starter Dependencies):提供一组预置依赖描述符,简化Maven/Gradle配置(如spring-boot-starter-web)。
  • 生产就绪特性:提供监控端点(actuator)、健康检查、外部化配置等开箱即用的生产特性。

6.2 Spring Cloud的核心组件及其功能?

参考答案:
Spring Cloud是一套分布式系统解决方案的集合,基于Spring Boot构建,用于快速开发分布式系统中的常见模式(如配置管理、服务发现、熔断器等)。

  • 服务发现与注册Eureka / Nacos。服务提供者向注册中心注册自己,消费者从注册中心发现服务。
  • 客户端负载均衡Ribbon / LoadBalancer。在服务消费者端实现软负载均衡。
  • 声明式REST客户端Feign / OpenFeign。基于接口和注解,更优雅地调用HTTP API。
  • API网关Zuul / Spring Cloud Gateway。统一的入口,提供路由、过滤、限流、安全等功能。
  • 熔断器Hystrix / Resilience4j / Sentinel。防止服务雪崩,提供服务降级和熔断机制。
  • 分布式配置Spring Cloud Config。集中化管理所有环境的配置文件。

如需获取更多实战面试题宝典(Spring/MySQL/Redis/MongoDB/Elasticsearch/Kafka等),请持续关注本专栏《面试题宝典》系列文章。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值