📁第一部分:Spring基础 & 核心概念
1. 什么是Spring框架?
Spring是一个轻量级的开源框架,是为了解决企业级应用开发的复杂性而创建的。其核心是控制反转(IoC)和面向切面编程(AOP)。它的主要目标是简化Java开发,通过POJO(简单的Java对象)为基础的编程模型来促进良好的编程习惯。
2. Spring框架有哪些核心模块?
Spring框架由多个模块组成,主要包含:
Spring Core:核心容器,提供IoC和DI功能。
Spring AOP:面向切面编程的实现。
Spring Web MVC:构建Web应用程序的MVC框架。
Spring DAO/ JDBC:对JDBC的抽象封装,简化数据访问异常处理。
Spring ORM:对Hibernate、JPA等ORM框架的集成。
Spring Context:企业级服务支持,如JNDI、EJB等。
3. 什么是控制反转(IoC)和依赖注入(DI)?
IoC(控制反转):是一种设计思想,指的是将传统上由程序代码直接操控的对象控制权交给容器来实现。即不再由调用者创建被调用者,而是由Spring容器创建并管理对象。
DI(依赖注入):是IoC的具体实现方式。在程序运行时,由Spring容器动态地将依赖关系注入到组件中。
4. IoC容器有哪些优点?
解耦:将类之间的依赖关系从代码中剥离,由容器管理,降低耦合度。
可测试性:方便进行单元测试(如Mock对象)。
实例管理:自动管理对象的生命周期和作用域。
提高复用性和灵活性。
📦第二部分:IoC容器 & Bean详解
5. BeanFactory 和 ApplicationContext 有什么区别?
BeanFactory:是Spring最底层的接口,提供了最基本的IoC功能。采用懒加载机制(getBean时才初始化Bean)。
ApplicationContext:是BeanFactory的子接口,提供了更多企业级功能,如解析配置文件、事件发布、国际化支持等。采用预加载机制(创建上下文时就初始化大部分单例Bean)。
6. Spring Bean 的生命周期是怎样的?
Spring Bean的生命周期可以简单概括为四个主要阶段,但在源码层面较为复杂,核心流程如下:
实例化:通过反射创建Bean的实例。
属性赋值:为Bean的属性进行注入(依赖注入)。
初始化:
调用各种
Aware接口的回调(如BeanNameAware)。执行
BeanPostProcessor的前置处理。执行
InitializingBean的afterPropertiesSet方法以及自定义的init-method。执行
BeanPostProcessor的后置处理(这里是AOP动态代理生成的关键点)。
销毁:容器关闭时,调用
DisposableBean的destroy方法和自定义的destroy-method。
7. Spring Bean 的作用域有哪些?
singleton(默认):每个Spring IoC容器中只有一个Bean实例。
prototype:每次获取都会创建一个新的Bean实例。
request:每次HTTP请求创建一个Bean,仅限Web应用。
session:每个HTTP Session创建一个Bean,仅限Web应用。
application/ global-session:每个
ServletContext或全局Session创建一个Bean。
8. 单例Bean是线程安全的吗?
Spring框架中的单例Bean不是线程安全的。
因为单例Bean是全局共享的,如果Bean中定义了可变的成员变量,在多线程并发修改时就会出现线程安全问题。
解决方案:
尽量设计无状态的Bean(大部分Service和DAO都是无状态的,只有方法逻辑,没有成员变量)。
使用
ThreadLocal来保存可变状态,为每个线程提供独立的变量副本。
9. 什么是循环依赖?Spring是如何解决的?
定义:循环依赖是指在对象创建过程中,A依赖B,B依赖A,形成闭环。
解决方案:
Spring通过三级缓存解决了
singleton + setter注入的循环依赖。一级缓存
singletonObjects:存放已经初始化完成的成品Bean。二级缓存
earlySingletonObjects:存放提前暴露的、未完全初始化的半成品Bean。三级缓存
singletonFactories:存放ObjectFactory,用于生成对象的早期引用,主要目的是为了解决AOP代理问题。
无法解决的场景:
构造器注入的循环依赖:因为此时对象还未实例化,无法提前暴露引用。
prototype作用域的Bean:因为Spring不缓存prototype类型的Bean。
10. 为什么要使用三级缓存?二级不够吗?
二级缓存也可以解决循环依赖,但引入三级缓存的核心原因是为了处理AOP代理。如果Bean需要被AOP增强,那么在实例化后直接返回原始对象,后续就无法生成代理对象了。三级缓存中存的ObjectFactory,可以在需要早期引用时调用其getEarlyBeanReference方法,提前生成代理对象,确保注入的依赖是最终的代理对象。
11. @Autowired 和 @Resource 的区别是什么?
@Autowired:由Spring提供。默认按照byType(类型)装配。如果类型匹配到多个Bean,则配合
@Qualifier按byName装配。@Resource:由Java标准(JSR-250)提供。默认按照byName(名称)装配。如果找不到名称匹配的Bean,则回退为byType进行装配。
12. 将一个类声明为Bean的注解有哪些?
@Component:通用的注解,标识该类为Spring组件。@Repository:标识数据访问层(DAO)。@Service:标识业务逻辑层(Service)。@Controller:标识表示层(Web层)。
13. @Component 和 @Bean 的区别是什么?
作用对象不同:
@Component作用于类,通过类路径扫描自动装配;@Bean作用于方法,通常用于将第三方库中的类实例化为Bean。创建方式不同:
@Component是Spring自动发现并创建;@Bean是程序员手动编写方法逻辑,显式创建并返回实例。
⚔️第三部分:面向切面编程(AOP)
14. 什么是AOP?它的应用场景有哪些?
AOP(面向切面编程)通过预编译方式和运行期动态代理,实现程序功能的统一维护。它可以将与业务无关但多个模块公用的逻辑(如日志记录、性能统计、安全控制、事务处理)封装起来,减少代码重复,降低耦合度。
15. Spring AOP 的底层实现原理是什么?
Spring AOP是基于动态代理实现的。
JDK动态代理:如果目标对象实现了接口,Spring会默认使用JDK动态代理。它通过反射生成一个实现同样接口的代理类。
CGLIB动态代理:如果目标对象没有实现接口,Spring会使用CGLIB库。CGLIB通过继承目标类,生成一个子类作为代理。
16. JDK动态代理和CGLIB动态代理的区别?
JDK动态代理:只能代理实现了接口的类,通过反射机制处理。
CGLIB动态代理:可以代理没有接口的类,通过生成目标类的子类来实现。因此,
final修饰的方法或类无法被CGLIB代理。
17. AOP中的关键术语(Joinpoint, Pointcut, Advice, Aspect)
连接点(Joinpoint):程序执行过程中的某个点,如方法调用、异常抛出。在Spring AOP中,连接点特指方法的执行。
切点(Pointcut):匹配连接点的表达式,用于定位需要在哪些连接点上执行通知。
通知(Advice):在特定切点上执行的具体增强逻辑(如Before, After, Around)。
切面(Aspect):切点(Pointcut)和通知(Advice)的组合,共同定义了“在哪里”和“做什么”。
18. 通知(Advice)的类型有哪些?
@Before:在方法执行前执行。
@After:在方法执行后执行(无论是否抛出异常)。
@AfterReturning:在方法成功返回后执行。
@AfterThrowing:在方法抛出异常后执行。
@Around:环绕通知,可以在方法调用前后自定义行为,甚至可以控制方法是否执行。
💾第四部分:Spring事务管理
19. Spring支持的事务管理方式有哪些?
编程式事务:通过编写代码(如
TransactionTemplate)手动管理事务的提交和回滚。代码侵入性强,但粒度更细。声明式事务:基于AOP,通过
@Transactional注解或XML配置来管理事务。这种方式更常用,代码侵入性低。
20. Spring事务的传播行为有哪些?
事务传播行为定义了事务方法在被另一个事务方法调用时,事务该如何传播。常用的是前三种:
REQUIRED(默认):支持当前事务,如果不存在则创建新事务。
REQUIRES_NEW:创建新事务,如果当前存在事务则挂起当前事务。
NESTED:如果当前存在事务,则在嵌套事务内执行(依赖底层JDBC的savepoint)。
SUPPORTS:支持当前事务,如果不存在则以非事务方式执行。
NOT_SUPPORTED:以非事务方式执行,如果存在当前事务则挂起。
MANDATORY:强制要求当前存在事务,否则抛出异常。
NEVER:必须以非事务方式执行,如果存在事务则抛出异常。
21. Spring事务的隔离级别有哪些?
隔离级别解决并发事务导致的数据不一致问题(脏读、不可重复读、幻读),通常使用数据库默认的隔离级别:
DEFAULT:使用底层数据库的默认隔离级别。
READ_UNCOMMITTED:读未提交。
READ_COMMITTED:读已提交。
REPEATABLE_READ:可重复读。
SERIALIZABLE:串行化。
22. 什么时候 @Transactional 注解会失效?
这是高频考点,常见失效场景如下:
异常被捕获:方法内部用
try-catch捕获了异常,没有抛出,导致Spring无法感知异常而回滚。抛出检查时异常:默认只回滚
RuntimeException和Error,抛出非运行时异常(如Exception)不回滚。需通过rollbackFor = Exception.class指定。非public方法:Spring默认只对
public方法进行代理增强。方法内部自调用:同一个类中的方法A调用方法B,即使B加了
@Transactional,由于没有经过代理对象,事务也会失效。数据库引擎不支持事务:如MySQL的MyISAM引擎。
🌐第五部分:Spring MVC
23. Spring MVC 的执行流程是怎样的?
用户发送请求,被前端控制器
DispatcherServlet拦截。DispatcherServlet调用处理器映射器HandlerMapping,根据请求URL找到具体的处理器Handler(即Controller)。DispatcherServlet根据获取到的Handler,选择合适的处理器适配器HandlerAdapter。HandlerAdapter调用具体的Controller执行请求逻辑,并返回ModelAndView对象。DispatcherServlet将ModelAndView交给视图解析器ViewResolver,解析成真正的视图View。DispatcherServlet对视图进行渲染(将Model数据填充到View中)。DispatcherServlet将最终的视图响应给用户。
24. 什么是DispatcherServlet?DispatcherServlet是Spring MVC的前端控制器。它是一个Servlet,负责接收所有HTTP请求,并将其委派给相应的组件(如控制器、视图解析器)进行处理,从而实现了请求处理流程的统一控制。
25. 如果在Controller中想接收JSON数据,应该用什么注解?
使用@RequestBody注解。它会将HTTP请求体中的JSON字符串绑定到对应的Java对象上。
26. 如果想返回JSON数据,应该在类或方法上加什么注解?
@ResponseBody:加在方法上,表示该方法的返回值直接写入HTTP响应体中,而不是解析为视图路径。
@RestController:组合注解,等同于
@Controller+@ResponseBody,现在开发RESTful API时最常用。
27. @RequestMapping 有什么用?
它是一个映射注解,用于将HTTP请求映射到控制器的处理方法上。可以在类级别(定义根路径)和方法级别(定义具体子路径)使用。
🚀第六部分:Spring Boot 核心
28. Spring Boot 的核心注解 @SpringBootApplication 是什么?
它是一个组合注解,包含以下三个主要注解:
@SpringBootConfiguration:本质上是一个
@Configuration,表示该类是一个配置类。@EnableAutoConfiguration:启动自动配置,让Spring Boot根据类路径中的依赖自动配置Bean。
@ComponentScan:启用组件扫描,自动扫描当前包及其子包下的
@Component等注解。
29. Spring Boot 的自动配置原理是什么?
Spring Boot在启动时,会通过@EnableAutoConfiguration注解,从类路径下的META-INF/spring.factories(Spring Boot 2.x)或META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(Spring Boot 3.x)文件中加载一大批预定义的自动配置类(XxxAutoConfiguration)。
这些配置类中大量使用了条件注解(如@ConditionalOnClass,@ConditionalOnMissingBean等),只有当满足特定条件时(比如classpath下有某个类,或用户没有自定义某个Bean),该自动配置才会生效。
30. Spring Boot Starter 是什么?
Starter是一组方便的依赖描述符。它聚合了特定功能所需的所有依赖(包括传递依赖),开发者只需要在项目中引入这一个starter,就可以获得该功能的所有依赖和自动配置支持,无需再手动添加大量jar包。
31. Spring Boot 中的 application.properties 和 application.yml 有什么区别?
两者都是Spring Boot的配置文件,只是格式不同。
properties:使用点分键值对的形式,结构简单。
YAML/YML:使用缩进表示层级关系,结构清晰,可读性高,特别适合表示列表和Map等数据结构。
32. Spring Boot Actuator 有什么作用?
Actuator 是 Spring Boot 提供的用于对应用系统进行监控和管理的功能模块。通过HTTP端点或JMX,可以查看应用的运行状态、健康情况、指标(Metrics)、环境属性、日志信息等。
33. Spring Boot 中如何实现异步方法?
在启动类或配置类上添加
@EnableAsync注解,开启异步支持。在需要异步执行的方法上添加
@Async注解。Spring会将该方法的执行提交到线程池中,调用者不会阻塞等待结果。
34. Spring Boot 中如何定制内嵌的Servlet容器(如Tomcat)?
可以通过在配置文件中配置server相关的属性(如server.port,server.servlet.context-path等),或者通过注册WebServerFactoryCustomizer组件来实现更细粒度的控制。
☁️第七部分:Spring Cloud 微服务
35. 什么是微服务?为什么使用Spring Cloud?
微服务是一种架构风格,它将一个大型复杂应用拆分成一组小型的、独立的服务,每个服务围绕业务能力构建,可独立开发、部署和扩展。
Spring Cloud 是基于 Spring Boot 的微服务解决方案,它为开发者提供了在分布式系统中快速构建一些常见模式(如配置管理、服务发现、断路器、智能路由、微代理等)的工具。
36. Spring Cloud 主要有哪些核心组件?
服务注册与发现:Netflix Eureka / Alibaba Nacos。
服务调用:OpenFeign(声明式HTTP客户端)。
负载均衡:Spring Cloud LoadBalancer。
服务熔断与降级:Resilience4J / Alibaba Sentinel。
API网关:Spring Cloud Gateway。
配置中心:Spring Cloud Config / Alibaba Nacos。
37. 什么是服务熔断和降级?
熔断:当某个服务故障或响应超时,为了防止整个系统出现雪崩,暂时切断对该服务的调用,直接返回错误。类似于电路跳闸。
降级:当服务器压力剧增时,根据业务策略放弃一些非核心功能,或者提供一种备选的、简化的返回结果,以保证核心功能的可用性。
38. Spring Cloud Gateway 的作用是什么?
Gateway是Spring Cloud官方推出的API网关。它作为系统的统一入口,负责将所有客户端的请求路由到后端的微服务。它还可以实现统一认证、日志、限流、跨域处理等功能。
39. OpenFeign 的工作原理是什么?
OpenFeign 是一个声明式的HTTP客户端。开发者只需定义一个Java接口,并在接口上添加@FeignClient注解,OpenFeign就会在运行时通过动态代理生成接口的实现类。它会根据注解中的信息(服务名、请求路径等),自动构建HTTP请求并调用远程服务,同时集成了负载均衡的功能。
40. 分布式系统中,什么是分布式事务?
分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单的数据库本地事务无法解决跨服务的操作一致性问题。常见的解决方案有:两阶段提交(2PC)、TCC(Try-Confirm-Cancel)模式、可靠消息最终一致性、Seata框架等。
📚第八部分:设计模式 & 其他
41. Spring框架中用了哪些设计模式?
工厂模式:
BeanFactory和ApplicationContext用于创建Bean实例。单例模式:Spring中Bean的默认作用域就是单例。
代理模式:AOP的实现核心。
模板方法模式:
JdbcTemplate,RestTemplate等Template类。观察者模式:Spring事件驱动模型(
ApplicationEvent,ApplicationListener)。适配器模式:Spring MVC中的
HandlerAdapter,用于适配不同类型的Controller。
42. 什么是Bean的自动装配?有哪些模式?
自动装配是指Spring容器在不使用<constructor-arg>和<property>标签的情况下,自动建立Bean之间的依赖引用关系。
模式有:no,byName,byType,constructor。
43. @Qualifier 注解的作用是什么?
当使用@Autowired自动装配时,如果存在多个类型相同的Bean,Spring就会不知道注入哪个。此时使用@Qualifier("beanName")配合@Autowired,可以根据Bean的名称来指定注入哪个具体的实现类。
44. @Primary 注解的作用是什么?
当有多个相同类型的Bean时,给其中一个Bean标记@Primary,它会成为自动装配时的首选Bean。如果同时使用了@Qualifier,则@Qualifier优先级更高。
45. Spring 的事件机制是什么?
Spring 的事件(Application Event)为Bean与Bean之间提供了消息通信的支持。它遵循观察者模式。当一个Bean发布事件(ApplicationEvent)后,所有对该事件感兴趣的监听者(ApplicationListener)都会收到通知并处理。
46. Spring 如何管理数据库连接池?
Spring本身不提供连接池实现,但它可以集成第三方连接池(如HikariCP、Druid、C3P0)。在Spring Boot中,默认使用HikariCP作为数据源,只需在配置文件中配置spring.datasource相关的连接信息即可。
47. 什么是JdbcTemplate?JdbcTemplate是Spring对JDBC的封装模板类。它简化了JDBC的使用步骤(如获取连接、创建语句、释放资源),使开发者只需关注SQL语句和结果集的提取,从而大大减少了样板代码。
48. Spring Boot 中如何读取配置文件中的自定义属性?
使用
@Value("${property.name}")注解注入单个属性。使用
@ConfigurationProperties(prefix = "my")绑定一个属性前缀,将一组属性映射到一个Java Bean上。
49. Spring Boot 支持哪些内嵌的Servlet容器?
Spring Boot默认支持内嵌的Tomcat(默认)、Jetty和Undertow。可以通过修改依赖(排除Tomcat,引入其他容器的starter)来切换。
50. Spring Data JPA 和 Hibernate 的关系是什么?
JPA(Java Persistence API)是一种规范/接口,定义了对象关系映射的API标准。
Hibernate是JPA规范的一种实现。Spring Data JPA在Hibernate核心功能的基础上,又封装了一层,提供了更便捷的Repository层抽象,进一步简化了数据访问操作。