当前位置: 首页 > ds >正文

【2025版】Spring Boot面试题

文章目录

  • 1. Spring, Spring MVC, SpringBoot是什么关系?
  • 2. 谈一谈对Spring IoC的理解
  • 3. @Component 和 @Bean 的区别?
  • 4. @Autowired 和 @Resource 的区别?
  • 5. 注入Bean的方法有哪些?
  • 6. 为什么Spring 官方推荐构造函数注入?
  • 7. Bean 的作用域有哪些?
  • 8. Bean 是线程安全的吗?
  • 9. Bean 的生命周期了解吗?
  • 10. 如何解决 Spring 中的循环依赖问题?
  • 11. @Lazy能解决循环依赖问题吗?
  • 12. Spring 动态代理默认用哪一种?
  • 13. Spring中拦截器和过滤器的区别?
  • 14. Spring Boot的配置优先级
  • 15. Spring Boot 自动配置如何实现的?
  • 16. @PathVariable 和 @RequestParam 的区别?
  • 17. Spring MVC的工作流程?
  • 18. Spring Boot 支持哪些嵌入式 web 容器?
  • 19. 介绍一下@SpringBootApplication注解
  • 20. Spring Boot 常用的两种配置文件是什么?
  • 21. 如何使用Spring Boot实现全局异常处理?
  • 22. Spring 中如何实现定时任务?多节点重复执行如何避免?
  • 23. 你的项目是如何统一返回结果的?
  • 24. 什么是Spring Boot Starters?
  • 25. Spring Boot 的主要优点?
  • 26. Spring Boot 是如何通过 main 方法启动 web 项目的?
  • 27. 如何在 Spring Boot 中读取配置信息?
  • 28. Spring 事务中哪几种事务传播行为?
  • 29. Spring 中BeanFactory 和 FactoryBean是什么?
  • 30. ApplicationContext是什么?
  • 31. Spring Boot 如何做请求参数校验?
  • 32. Spring Boot 如何处理跨域请求?
  • 33. Spring Boot 如何实现异步处理?
  • 34. 说说对 Spring 中事件机制的理解?
  • 35. Spring 中如何配置多数据源?
  • 36. Spring 中有哪些设计模式?
  • 37. Spring AOP 如何使用?
  • 38. @Primary 和 @Qualifier注解的作用是什么?
  • 39. @RequestBody和@ResponseBody注解的作用是什么?

1. Spring, Spring MVC, SpringBoot是什么关系?

Spring 包含了多个功能模块,Spring MVC是其中一个模块,专门处理Web请求。Spring Boot 只是简化了配置,如果需要构建 MVC 架构的 Web 程序,还是需要使用 Spring MVC 作为 MVC 框架,只是说 Spring Boot 简化了 Spring MVC 的很多配置,真正做到开箱即用。

2. 谈一谈对Spring IoC的理解

IoC(Inversion of Control:控制反转) 将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理。

为什么叫控制反转?
控制:指的是对象创建(实例化、管理)的权力
反转:控制权交给外部环境(Spring 框架、IoC 容器)

3. @Component 和 @Bean 的区别?

  • @Component 注解作用于类,而@Bean注解作用于方法。
  • 当我们引用第三方库中的类需要装配到 Spring容器时,则只能通过 @Bean来实现。

4. @Autowired 和 @Resource 的区别?

@Autowired 属于 Spring 内置的注解,默认的注入方式为byType(根据类型进行匹配),也就是说会优先根据接口类型去匹配并注入 Bean (接口的实现类)。 当一个接口存在多个实现类的话,byType这种方式就无法正确注入对象了,因为这个时候 Spring 会同时找到多个满足条件的选择,默认情况下它自己不知道选择哪一个。这种情况下,注入方式会变为 byName(根据名称进行匹配),这个名称通常就是类名(首字母小写)。
通过 @Qualifier 注解可以来显式指定名称而不是依赖变量的名称。

@Resource属于 JDK 提供的注解,默认注入方式为 byName。如果无法通过名称匹配到对应的 Bean 的话,注入方式会变为byType
@Resource 有两个比较常用的属性:name(名称)、type(类型)。如果仅指定 name 属性则注入方式为byName,如果仅指定type属性则注入方式为byType,如果同时指定name 和type属性(不建议这么做)则注入方式为byType+byName。

5. 注入Bean的方法有哪些?

  • 构造函数注入:通过类的构造函数来注入依赖项。
  • Setter 注入:通过类的 Setter 方法来注入依赖项。
  • Field(字段) 注入:直接在类的字段上使用注解(如 @Autowired 或 @Resource)来注入依赖项。

6. 为什么Spring 官方推荐构造函数注入?

  • 依赖完整性:确保所有必需依赖在对象创建时就被注入,避免了空指针异常的风险。
  • 不可变性:有助于创建不可变对象,提高了线程安全性。
  • 初始化保证:组件在使用前已完全初始化,减少了潜在的错误。
  • 测试便利性:在单元测试中,可以直接通过构造函数传入模拟的依赖项,而不必依赖 Spring 容器进行注入。

7. Bean 的作用域有哪些?

  • singleton : IoC 容器中只有唯一的 bean 实例。Spring 中的 bean 默认都是单例的,是对单例设计模式的应用。
  • prototype : 每次获取都会创建一个新的 bean 实例。也就是说,连续 getBean() 两次,得到的是不同的 Bean 实例。
  • request : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。
  • session : 每一个 HTTP Session 会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。

8. Bean 是线程安全的吗?

Spring 框架中的 Bean 是否线程安全,取决于其作用域和状态

几乎所有场景的 Bean 作用域都是使用默认的singleton ,重点关注 singleton 作用域即可。prototype 作用域下,每次获取都会创建一个新的 bean 实例,不存在资源竞争问题,所以不存在线程安全问题。

singleton 作用域下,IoC 容器中只有唯一的 bean 实例,可能会存在资源竞争问题(取决于 Bean 是否有状态)。如果这个 bean 是有状态的话,那就存在线程安全问题(有状态 Bean 是指包含可变的成员变量的对象)。

9. Bean 的生命周期了解吗?

在这里插入图片描述
Bean的生命周期从Spring容器启动开始,首先根据配置或注解扫描获取Bean的定义信息,随后通过反射实例化对象并填充属性,完成依赖注入。如果Bean实现了诸如BeanNameAware等Aware接口,容器会在此阶段回调相关方法使其感知自身信息。接下来,BeanPostProcessor的postProcessBeforeInitialization方法被调用,执行初始化前的自定义逻辑,例如处理@PostConstruct注解的方法。随后容器触发初始化回调,包括InitializingBean接口的afterPropertiesSet方法或通过XML、注解定义的初始化方法。BeanPostProcessor的postProcessAfterInitialization在此之后执行,常见于生成AOP代理对象等增强处理。此时Bean已就绪,可被应用程序使用。当容器关闭时,销毁流程启动,依次执行@PreDestroy注解的方法、DisposableBean接口的destroy方法或配置的销毁方法,最终完成Bean的资源释放与生命周期终结。

10. 如何解决 Spring 中的循环依赖问题?

Spring通过三个缓存层级解决单例Bean的循环依赖问题:

缓存名称描述
singletonObjects一级缓存:存放完全初始化好的Bean(成品对象)。
earlySingletonObjects二级缓存:存放早期暴露的Bean(已实例化但未填充属性,未初始化)。
singletonFactories三级缓存:存放Bean的工厂对象(ObjectFactory),用于生成早期引用。

以A依赖B,B依赖A为例:

  1. 创建Bean A

    • 实例化A:调用A的构造函数创建对象(此时对象未填充属性,未初始化)。

    • 将A的工厂对象放入三级缓存(singletonFactories),用于后续生成早期引用。

    • 填充A的属性:发现需要注入B。

  2. 创建Bean B

    • 实例化B:调用B的构造函数创建对象。

    • 将B的工厂对象放入三级缓存。

    • 填充B的属性:发现需要注入A。

  3. 解决B对A的依赖

    • 从三级缓存中获取A的工厂对象(singletonFactories),生成A的早期引用(通过getEarlyBeanReference方法)。这一步是整合了第一步那个实例化但是没在任何缓存里的A对象,给他变成了半成品代理对象(如果A有被代理的话)

    • 将A的早期引用存入二级缓存(earlySingletonObjects),并从三级缓存中删除A的工厂。

    • 将A的早期引用注入到B中,完成B的属性填充和初始化。

    • 将初始化后的B存入一级缓存(singletonObjects)。

  4. 完成A的创建

    • 从一级缓存中获取已初始化的B,注入到A中。

    • 完成A的属性填充和初始化。

    • 将A存入一级缓存,并从二级缓存中删除A的早期引用。

我直接在实例化的时候判断A有没有代理,如果有的话,我直接把代理对象放到二级缓存里不行吗?这样就不用三级缓存了

代理对象应该在bean 实例化→属性填充→初始化 做完之后才去生成的(bean的生命周期),假设没有出现循环依赖,bean能通过正常的生命周期生成代理,我们直接在bean没完成初始化前就生成代理对象了,就打乱了bean的生命周期了。

通过三级缓存,可以推迟bean的早期引用暴露,也就是说,要不要提前生成代理对象这个事情,推迟到循环依赖真正发生的时候。如果真发生了循环依赖,B才会调用getEarlyBeanReference方法生成A的代理,如果没循环依赖的话,在二级缓存正常放填充好属性的A对象的,就不用提前把A的代理放二级缓存了。

注意点:

  • 仅支持单例Bean的循环依赖
    原型(Prototype)作用域的Bean无法通过缓存解决循环依赖,Spring会直接抛出异常。
  • 构造器注入无法解决循环依赖
    如果循环依赖通过构造函数参数注入(而非Setter方法或字段注入),Spring无法提前暴露对象,会抛出BeanCurrentlyInCreationException。

解释:如果两个Bean都是原型模式的话,那么创建A1需要创建一个B1,创建B1的时候要创建一个A2,创建A2又要创建一个B2,创建B2又要创建一个A3,创建A3又要创建一个B3,循环依赖就没办法解决了。

如果A和B的依赖都是通过构造器注入,那连一个半成品对象都创建不出来,也没办法解决循环依赖

11. @Lazy能解决循环依赖问题吗?

在一定程度上是能解决的

  1. Spring 创建 A 时,发现它依赖 B,但 B 被标记为 @Lazy。

  2. 不立即初始化 B,而是注入一个 B 的代理对象(由 Spring 动态生成)。

  3. 当 A 的方法首次调用 b.xxx() 时,代理对象才会触发 B 的实际初始化。

  4. 此时 B 初始化时再去注入 A,由于 A 已经存在,循环依赖被解开。

12. Spring 动态代理默认用哪一种?

Spring Boot 2.x 及以上版本默认启用了 proxyTargetClass=true,因此无论目标类是否实现接口,统一使用 CGLIB 生成代理。
动态代理的使用

13. Spring中拦截器和过滤器的区别?

过滤器(Filter)是Servlet规范的一部分,其作用范围覆盖整个Web应用,能够处理所有进入Servlet容器的请求,例如修改请求参数、设置字符编码或实现全局安全控制。它的执行时机在请求到达DispatcherServlet之前,因此可以作用于静态资源等非Spring管理的请求。

拦截器(Interceptor)是Spring MVC框架提供的组件,其实现依赖于HandlerInterceptor接口,通过Spring的配置类注册到拦截器链中。它的核心作用范围集中在Spring管理的控制器(Controller)层,能够在请求进入具体Controller方法前(preHandle)、方法执行后视图渲染前(postHandle)以及整个请求完成后(afterCompletion)这三个关键节点插入逻辑。所以拦截器更适合处理与业务紧密相关的操作,例如基于会话的权限校验、日志记录或接口性能监控。从执行顺序上看,整体上过滤器的处理会先于拦截器完成。过滤器更偏向底层请求的通用处理,而拦截器则聚焦于Spring MVC流程中的业务逻辑增强。

HTTP Request → Servlet Filter (过滤请求) → DispatcherServlet → Interceptor.preHandle() → Controller → Interceptor.postHandle() → Interceptor.afterCompletion()

14. Spring Boot的配置优先级

从高到低:

  • 命令行参数(–key=value)
  • java系统属性(-Dkey=value)
  • application.properties
  • application.yml

15. Spring Boot 自动配置如何实现的?

https://blog.csdn.net/fim77/article/details/146459033

16. @PathVariable 和 @RequestParam 的区别?

@PathVariable用于获取路径参数 /users/{id} → /users/123

@RequestParam用于获取查询参数。/users?id=123

17. Spring MVC的工作流程?

图片来自面试鸭用户:https://www.mianshiya.com/user/1815995005551374337
请添加图片描述

18. Spring Boot 支持哪些嵌入式 web 容器?

SpringBoot提供了三种内嵌Web容器,分别为Tomcat、Jetty和Undertow。

当你在项目中引入spring-boot-starter-web这个起步依赖时,Spring Boot默
认会包含并启用Tomcat作为内嵌Servlet容器。

如果你想使用Jetty或Undertow,需要在构建文件(如Maven的pom.xml或
Gradle 的build.gradle)中,从spring-boot-starter-web 中排除默认的
Tomcat 依赖(spring-boot-starter-tomcat),添加你想使用的容器对应的
Starter 依赖(例如spring-boot-starter-jetty 或spring-boot-starter-un
dertow)

19. 介绍一下@SpringBootApplication注解

@SpringBootApplication是SpringBoot项目的核心注解,通常用于标记应用程
序的主类(即包含main方法的类)。它的主要作用是一站式地启用SpringBoot的
关键特性,简化项目的初始配置。

  • @SpringBootConfiguration​​
    继承自 @Configuration,标记当前类为配置类,允许通过 @Bean 注解定义和注册 Bean。
  • ​​@EnableAutoConfiguration​​
    启用 Spring Boot 的自动配置机制。根据项目依赖中META-INF/下后缀为.imports 文件加载预定义的配置类,结合条件注解(如 @ConditionalOnClass)自动配置 Spring 应用所需的 Bean。
  • @ComponentScan​​
    默认扫描当前类所在包及其子包下的组件,并将它们注册为 Spring Bean。

20. Spring Boot 常用的两种配置文件是什么?

  1. application.properties
    采用标准的JavaProperties文件格式,即键值对(key=value)的形式,每一行定义一个配置项。
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
  1. application.yml(或yaml)
    采用YAML(YAMLAin’tMarkupLanguage)格式,这是一种层级化、以缩进表示结构的数据序列化语言。相比.properties文件,YAML 格式通常更易于阅读,尤其是
    在配置项较多或具有嵌套结构时,结构更清晰。并且,对于具有共同前缀的配置项,YAML可以通过层级嵌套避免重复书写前缀,使配置更简洁。
server:port: 8080
spring:datasource:url: jdbc:mysql://localhost:3306/mydb

21. 如何使用Spring Boot实现全局异常处理?

在 Spring Boot 中,可以通过 ​​@ControllerAdvice​​ 和 ​​@ExceptionHandler​​ 注解实现全局异常处理。

@RestControllerAdvice
public class GlobalExceptionHandler {// 处理自定义异常@ExceptionHandler(BusinessException.class)public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex) {ErrorResponse error = new ErrorResponse(ex.getCode(), ex.getMessage());return ResponseEntity.status(ex.getHttpStatus()).body(error);}// 处理所有未捕获的异常@ExceptionHandler(Exception.class)public ResponseEntity<ErrorResponse> handleGenericException(Exception ex) {ErrorResponse error = new ErrorResponse("ERROR_500", "系统内部错误");return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);}
}

22. Spring 中如何实现定时任务?多节点重复执行如何避免?

在 Spring Boot 主类或配置类上添加 @EnableScheduling

@SpringBootApplication
@EnableScheduling
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

使用 @Scheduled注解标记方法,支持 cron、fixedRate、fixedDelay 等参数

@Component
public class MyScheduledTasks {// 每 5 秒执行一次@Scheduled(fixedRate = 5000)public void doTask() {System.out.println("执行定时任务: " + new Date());}
}

Spring Task 在多节点部署时,如果不采取措施,每个节点都会执行相同的定时任务,导致重复执行。这主
要是因为每个节点上都运行着独立的 Spring 容器,每个容器都拥有自己的定时任务调度器,并独立地根据
配置的时间触发任务,互不干扰。如果多个节点的配置相同,就会导致同一任务在多个节点上并发执行。
这种情况不仅浪费资源,还可能导致数据不一致、资源竞争等问题,最终导致业务逻辑错误,例如重复处
理相同的数据、发送重复的通知。

解决方法:

  1. 分布式锁
  2. 分布式任务调度工具,如XXL-JOB

23. 你的项目是如何统一返回结果的?

code: 状态码,遵循HTTP状态码规范并扩展业务状态码

message: 对状态的描述信息

data: 实际返回的业务数据

timestamp: 响应时间戳

  1. 手动显式封装
    @GetMapping("/{id}")public Result<User> getUser(@PathVariable Long id) {User user = userService.getUserById(id);return Result.success(user);}
  1. 自动封装
@RestControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice<Object> {@Overridepublic boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {// 判断是否需要包装return !returnType.getParameterType().equals(Result.class);}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {return Result.success(body);}
}

24. 什么是Spring Boot Starters?

Spring Boot Starters 是一组便捷的依赖描述符,它们预先打包了常用的库和配置。当我们开发 Spring 应
用时,只需添加一个 Starter 依赖项,即可自动引入所有必要的库和配置,而无需手动逐一添加和配置相关
依赖。

这种机制显著简化了开发过程,特别是在处理复杂项目时尤为高效。通过添加一个简单的Starter 依赖,开
发者可以快速集成所需的功能,避免了手动管理多个依赖的繁琐和潜在错误。这不仅节省了时间,还减少
了配置错误的风险,从而提升了开发效率。

25. Spring Boot 的主要优点?

  1. 显著提升开发效率:Spring Boot 通过自动配置、起步依赖(Starters)和其他开箱即用的功能,极大地减少了项目初始化、配置编写和样板代码的工作量,使开发者能更快地构建和交付应用。

  2. 与 spring 生态系统的无缝集成:作为 Spring 家族的一员,Spring Boot 能够方便地整合 Spring 框架下的其他成熟模块(如 Spring Data、Spring Security、Spring Batch 等),充分利用 Spring 强大的生态系统,简化整合工作。

  3. 强大的自动配置能力:遵循“约定优于配置”的原则,Spring Boot 能够根据项目依赖自动配置大量
    的常见组件(如数据源、Web 容器、消息队列等),提供合理的默认设置。同时也允许开发者根据需
    要轻松覆盖或定制配置,极大减少了繁琐的手动配置工作。

  4. 内嵌 Web 服务器支持:Spring Boot 自带内嵌的 HTTP服务器(如 Tomcat、Jetty),开发者可以像运行普通 Java 程序一样运行 Spring Boot 应用程序,极大地简化了开发和测试过程。

  5. 适合微服务架构:Spring Boot 使得每个微服务都可以独立运行和部署,简化了微服务的开发、测试和运维工作,成为构建微服务架构的理想选择。

  6. 提供强大的构建工具支持:Spring Boot为常用的构建工具(如 Maven和 Gradle)提供了专门的插件,简化了项目的打包(如创建可执行JAR)、运行、测试以及依赖管理等常见构建任务丰富的监控和管理功能:通过 Spring Boot Actuator 模块,可以轻松地为应用添加生产级的监控和管理端点,方便了解应用运行状况、收集指标、进行健康检查等。

26. Spring Boot 是如何通过 main 方法启动 web 项目的?

https://www.mianshiya.com/bank/1797452903309508610/question/1846441429268488194#heading-14

27. 如何在 Spring Boot 中读取配置信息?

  1. 使用 @Value 注解
    // 直接注入配置项,支持默认值(如未配置则使用默认值)@Value("${book.author:defaultAuthor}")private String author;
  1. 使用 @ConfigurationProperties 注解
# 配置文件 application.yml
book:name: 三国演义author: 罗贯中price: 30chapters:- 第一章- 第二章
@Component
@ConfigurationProperties(prefix = "book")
public class BookProperties {private String name;private String author;private int price;private List<String> chapters;
}
  1. 使用 Environment 接口
 @Autowiredprivate Environment env;public String getAppInfo() {String appName = env.getProperty("app.name");String maxRetry = env.getProperty("app.max-retry", "defaultRetry");}

28. Spring 事务中哪几种事务传播行为?

总共有7种,常用的就前两种

  1. PROPAGATION_REQUIRED(默认)
    如果当前存在事务,则加入该事务;否则新建一个事务。
    所有嵌套方法共享同一个事务,任一方法抛出异常会导致整个事务回滚。
  2. PROPAGATION_REQUIRES_NEW
    无论当前是否存在事务,都新建一个独立事务。
    内层事务与外层事务完全隔离,外层事务回滚不影响内层事务。
  3. PROPAGATION_NESTED
    如果当前存在事务,则在当前事务内嵌套一个子事务;否则创建新事务。
    子事务是父事务的一部分,但可以独立回滚。
    子事务回滚不影响父事务(需捕获异常),父事务回滚则子事务也会回滚。
  4. PROPAGATION_MANDATORY
    必须在一个已存在的事务中运行,否则抛出异常。
  5. PROPAGATION_SUPPORTS
    如果当前存在事务,则加入该事务;否则以非事务方式运行。
  6. PROPAGATION_NOT_SUPPORTED
    以非事务方式运行,如果当前存在事务则挂起。
  7. PROPAGATION_NEVER
    以非事务方式运行,如果当前存在事务则抛出异常。

29. Spring 中BeanFactory 和 FactoryBean是什么?

BeanFactory是Spring框架的核心接口,作为IoC容器的基础,负责管理Bean的生命周期,包括创建、配置和装配对象。

FactoryBean是一个特殊的Bean,可以在运行时根据特定条件或需求,通过getObject()方法动态控制Bean的实例化过程,在容器中通过名称前加&符号区分获取FactoryBean本身与其生产的对象。

30. ApplicationContext是什么?

ApplicationContext是Spring框架的核心容器接口,它作为高级容器不仅继承了BeanFactory的基础功能来管理和配置Bean,还扩展了众多企业级特性。它整合了资源加载、国际化支持、事件发布与监听机制,同时支持AOP、事务管理等高级功能。

31. Spring Boot 如何做请求参数校验?

  1. 验证请求体
    在 DTO 类上使用校验注解
public class UserDTO {@Size(min = 2, max = 20, message = "用户名长度必须在2-20之间")private String username;
}

在 Controller 中使用 @Valid 注解触发校验(@Validated也行)

@PostMapping("/users")
public ResponseEntity<?> createUser(@RequestBody @Valid UserDTO userDTO) {// 业务逻辑return ResponseEntity.ok("用户创建成功");
}
  1. 验证请求参数

直接在方法参数上使用校验注解:

@GetMapping("/users/{id}")
public ResponseEntity<?> getUserById(@PathVariable @Min(1) Long id) {// 业务逻辑return ResponseEntity.ok(...);
}

需要在 Controller 类上添加 @Validated 注解,只能在类上添加这个才有用

@RestController
@Validated
public class UserController {// ...
}

补充:分组校验

public class UserDTO {@NotBlank(message = "用户名不能为空", groups = {CreateGroup.class, UpdateGroup.class})private String username;@Email(message = "邮箱格式不正确", groups = CreateGroup.class) // 仅创建时需要校验邮箱private String email;@NotNull(message = "ID不能为空", groups = UpdateGroup.class)  // 仅更新时需要校验IDprivate Long id;// Getter 和 Setter
}
@PostMapping("/users")
public ResponseEntity<?> createUser(@RequestBody @Validated(CreateGroup.class) UserDTO userDTO) {return ResponseEntity.ok("创建用户校验通过");
}

32. Spring Boot 如何处理跨域请求?

一文搞懂Spring Boot处理跨域请求

33. Spring Boot 如何实现异步处理?

主要有四种方式来实现异步处理:

  1. 使用 @Async注解
  2. 使用 CompletableFuture
  3. 使用@Scheduled注解
  4. 使用线程池

34. 说说对 Spring 中事件机制的理解?

Spring 的事件机制是一种基于观察者模式设计的解耦通信方式,允许组件在特定动作发生时通过事件传递信息,而不必直接依赖彼此。开发者可以自定义继承 ApplicationEvent 的事件类,由事件发布者通过 ApplicationEventPublisher 触发事件,而监听者通过实现 ApplicationListener 接口或使用 @EventListener 注解来捕获并处理事件。这种机制默认以同步方式运行,但结合 @Async 或自定义线程池可支持异步处理,提升系统响应能力。例如,用户注册成功后发布事件,由监听器异步发送邮件或初始化数据,避免主流程阻塞。

35. Spring 中如何配置多数据源?

一文带你理清SpringBoot如何实现多数据源动态路由【全干货,无废话】

36. Spring 中有哪些设计模式?

  1. 工厂模式(Factory Pattern)
    作用:隐藏对象创建细节,由容器统一管理 Bean 的生命周期。
  2. 单例模式(Singleton Pattern)
    Spring 默认的 Bean 作用域为单例(singleton),确保每个容器中一个 Bean 仅有一个实例。
    作用:节省资源,保证全局一致性。
  3. 原型模式(Prototype Pattern)
    Bean 的作用域设为 prototype 时,每次请求都会创建新实例(如 @Scope(“prototype”))。
  4. 代理模式(Proxy Pattern)
    Spring AOP(面向切面编程)通过动态代理实现横切关注点(如事务、日志)。
  5. 模板方法模式(Template Method Pattern)
    JdbcTemplate、RestTemplate 等模板类封装通用流程,消除重复代码
  6. 观察者模式(Observer Pattern)
    核心应用:Spring 事件驱动模型(ApplicationEvent 和 ApplicationListener)。
  7. 适配器模式(Adapter Pattern)
    统一接口,兼容不同实现。
  8. 装饰者模式(Decorator Pattern)
    HttpServletRequestWrapper 包装 HTTP 请求,增强其行为(如缓存请求体)。
  9. 策略模式(Strategy Pattern)
    Spring MVC 的 HandlerMapping 根据请求匹配不同策略的处理器。
  10. 委派模式(Delegate Pattern)
    DispatcherServlet 将请求分发给不同的处理器(如 Controller、Handler)。
  11. 建造者模式(Builder Pattern)
    分步构建复杂对象。
  12. 责任链模式(Chain of Responsibility)
    Spring Security 的过滤器链(FilterChainProxy),每个过滤器依次处理请求。

37. Spring AOP 如何使用?

【25年最新AOP入门】最干净省时的SpringBoot AOP入门教程,一小时带你学会面向切面编程怎么用

38. @Primary 和 @Qualifier注解的作用是什么?

@Primary标记某个Bean为“默认首选”的候选对象。当存在多个相同类型的Bean时,Spring会优先选择带有@Primary注解的Bean进行注入。

@Qualifier通过显式指定 Bean 的名称或标识符来解决多个同类型 Bean 的冲突。

39. @RequestBody和@ResponseBody注解的作用是什么?

@RequestBody注解用于将HTTP请求体中的内容绑定到方法的参数上,它主要作用在方法的参数上。

@ResponseBody注解用于将方法的返回值直接写入HTTP响应体中,它可以标注在方法或类上。

在Spring 4.0之后,可以使用@RestController注解替代@Controller+@ResponseBody的组合

http://www.xdnf.cn/news/6308.html

相关文章:

  • C语言_自定义类型:结构体
  • (4)python开发经验
  • (十七)Java日期时间API全面解析:从传统Date到现代时间处理
  • Ros2 - Moveit2 - DeepGrasp(深度抓握)
  • golang -- 如何让main goroutine等一等
  • 数智驱动——AI:企业数字化转型的“超级引擎”
  • FreeRTOS学习笔记
  • 【Java学习笔记】finalize方法
  • 前后端分离博客 Weblog 项目实战
  • 【AI大模型】赋能【传统业务】
  • Java基础语法之数组
  • Windows下Docker安装portainer
  • 64. 最小路径和
  • Shell 脚本中的通道号(文件描述符)
  • maven项目, idea右上角一直显示gradle的同步标识, 如何去掉
  • 计算机网络:什么是计算机网络?它的定义和组成是什么?
  • 开源Heygem本地跑AI数字人视频教程
  • python使用matplotlib画图
  • IDEA编辑器设置的导出导入
  • why FPGA喜欢FMC子卡?
  • Vue3学习(组合式API——计算属性computed详解)
  • 使用Word2Vec算法实现古诗自动生成实战
  • Linux514 rsync 解决方案环境配置
  • 2025年渗透测试面试题总结-360[实习]安全工程师(题目+回答)
  • 三维CAD皇冠CAD(CrownCAD)建模教程:工程图模块二
  • 52页PPT | 企业数字化转型L1-L5数据架构设计方法论及案例数字化转型解决方案数字化规划方案
  • 回溯实战篇2
  • 今日行情明日机会——20250514
  • day25-异常处理
  • [Java实战]Spring Security 添加验证码(二十三)