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

【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的组合

相关文章:

【2025版】Spring Boot面试题

文章目录 1. Spring, Spring MVC, SpringBoot是什么关系&#xff1f;2. 谈一谈对Spring IoC的理解3. Component 和 Bean 的区别&#xff1f;4. Autowired 和 Resource 的区别&#xff1f;5. 注入Bean的方法有哪些&#xff1f;6. 为什么Spring 官方推荐构造函数注入&#xff1f;…...

C++——类和对象(1)

文章目录 一、前言二、类和对象上2.1 类的定义2.1.1 定义格式一2.1.2 定义格式二2.1.3 注意点 2.2 访问限定符2.2.1 访问限定符的用法 2.3 类域2.4 类的实例化2.4.1 实例化的概念2.4.2 实例化具体举例2.4.3类的实例化对象大小 2.5 this指针2.5.1 this指针的概念2.5.6 this指针的…...

【行为型之观察者模式】游戏开发实战——Unity事件驱动架构的核心实现策略

文章目录 &#x1f3af; 观察者模式&#xff08;Observer Pattern&#xff09;深度解析一、模式本质与核心价值二、经典UML结构三、Unity实战代码&#xff08;玩家血量监控系统&#xff09;1. 定义观察者接口与主题基类2. 实现具体主题&#xff08;玩家血量&#xff09;3. 实现…...

Java基础语法之数组

数组 一、认识数组 1.什么是数组 数组就是一个容器&#xff0c;用来存一批同种类型的数据。 举例 20, 10, 80, 60, 90 int[] arr {20, 10, 80, 60, 90};张三, 李四, 王五 String[] names {"张三", "李四", "王五"};2.为什么要使用数组 假设…...

Vue3学习(组合式API——计算属性computed详解)

目录 一、计算属性computed。 Vue官方提供的案例。(普通写法与计算属性写法) 使用计算属性computed重构——>简化描述响应式状态的复杂逻辑。 &#xff08;1&#xff09;计算属性computed小案例。 <1>需求说明。&#xff08;筛选原数组——>得新数组&#xff09; &…...

高海拔和远距离的人员识别:面部、体型和步态的融合

大家读完就觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 我们解决了在无约束环境中进行全身人体识别的问题。这个问题出现在诸如IARPA高空和远距离生物识别与身份识别&#xff08;BRIAR&#xff09;计划等监视场景中&#xff0c;其中生物识别数据是在长…...

《P2345 [USACO04OPEN] MooFest G》

题目背景 P5094 [USACO04OPEN] MooFest G 加强版 题目描述 约翰的 n 头奶牛每年都会参加“哞哞大会”。 哞哞大会是奶牛界的盛事。集会上的活动很多&#xff0c;比如堆干草&#xff0c;跨栅栏&#xff0c;摸牛仔的屁股等等。 它们参加活动时会聚在一起&#xff0c;第 i 头…...

浅浅学:DoIP工作流程及基于DoIP的诊断/刷写工具

注&#xff1a;阅读本文需要对UDS及BootLoader有一定了解&#xff0c;基础内容不做赘述。 在汽车"新四化"浪潮的推动下&#xff0c;智能座舱、自动驾驶、车路协同等创新技术正加速重构行业格局。随着车载ECU数量突破百个量级&#xff0c;软件代码量呈指数级增长——…...

首个专业AI设计Agent发布-Lovart

Lovart是什么 Lovart 是为设计师打造的世界上首个专业设计 Agent。Lovart 能像专业设计师一样思考和执行设计任务&#xff0c;提供高水平的设计方案。基于自然语言交互&#xff0c;用户能快速调整布局、颜色和构图。Lovart 支持从创意拆解到专业交付的全链路设计&#xff0c;单…...

二叉树(中序遍历)

嘿&#xff0c;欢迎来到小巫blog&#xff01;小巫又来啦&#xff01;看到你对二叉树中序遍历这道题有点困惑&#xff0c;别担心&#xff0c;我会一步步带你搞定它&#xff01;这道题是树的基础题目&#xff0c;掌握了它&#xff0c;你对树的遍历就会有很深的理解。我相信&#…...

Ubuntu 系统默认已安装 python,此处只需添加一个超链接即可

步骤 1&#xff1a;确认 Python 3 的安装路径 查看当前 Python 3 的路径&#xff1a; which python3 输出类似&#xff1a; /usr/bin/python3 步骤 2&#xff1a;创建符号链接 使用 ln -s 创建符号链接&#xff0c;将 python 指向 python3&#xff1a; sudo ln -s /usr/b…...

AcroForm JavaScript Promise 对象应用示例: 异步加载PDF文件

这段代码演示了在Adobe Acrobat DC Pro 的 JavaScript 环境中如何使用 Promise 对象处理异步操作。具体功能是&#xff1a; 定义了一个loadFile函数&#xff0c;模拟异步加载PDF文件的操作使用Promise对象封装异步操作&#xff0c;提供成功(resolve)和失败(reject)两种状态通过…...

LeetCode 热题 100 114. 二叉树展开为链表

LeetCode 热题 100 | 114. 二叉树展开为链表 大家好&#xff0c;今天我们来解决一道经典的二叉树问题——二叉树展开为链表。这道题在 LeetCode 上被标记为中等难度&#xff0c;要求将二叉树展开为一个单链表&#xff0c;展开后的单链表应该与二叉树的先序遍历顺序相同。 问题…...

DML和DQL

1. 设置MySQL的储存引擎 上一章的附录里已经将ini设置好了&#xff0c;不用再次设置 2. DML语句 插入单数据记录 插入多数据记录 将查询结果插入新表 更新数据 删除数据 注意&#xff1a;delete删除只会删除数据&#xff0c;不会重置表的现有逻辑&#xff0c;truncate会重置表逻…...

多线程与线程互斥

我们初步学习完线程之后&#xff0c;就要来试着写一写多线程了。在写之前&#xff0c;我们需要继续来学习一个线程接口——叫做线程分离。 默认情况下&#xff0c;新创建的线程是joinable的&#xff0c;线程退出后&#xff0c;需要对其进行pthread_join操作&#xff0c;否则无法…...

BMS工具箱用来执行贝叶斯模型平均(BMA)计算模块

贝叶斯模型平均&#xff08;Bayesian Model Averaging&#xff0c;BMA&#xff09;是一种用于处理模型不确定性的统计方法&#xff0c;通过结合多个模型的预测结果来提高预测的准确性和鲁棒性。在 MATLAB 中&#xff0c;可以使用专门的工具箱&#xff08;如 BMS 工具箱&#xf…...

Java死锁排查:线上救火实战指南

想象一下&#xff0c;你正在值班&#xff0c;突然监控告警红成一片&#xff0c;用户反馈雪花般飘来&#xff1a;“系统卡死了&#xff01;用不了了&#xff01;” —— 这很可能就是Java应用遭遇了“死锁”这个大魔王。这时候&#xff0c;你就是救火队长&#xff0c;首要任务不…...

第十九次博客打卡

今天学习的内容是Java中的常见循环。 在 Java 中&#xff0c;常见的循环结构主要有以下几种&#xff1a;for 循环、while 循环、do-while 循环以及增强型 for 循环&#xff08;也称为 for-each 循环&#xff09;。 1. for 循环 for 循环是一种非常灵活的循环结构&#xff0c…...

智能体制作学习笔记1——智能体

01 智能体_哔哩哔哩_bilibili 大语言模型可以理解成一个很厉害的人。 但是要完成一些特定的工作&#xff0c;除了大语言模型&#xff0c;还需要一些工具和业务流程&#xff0c;这样才能自动化帮我们完成特定的工作&#xff0c;这个就叫做智能体。 突然发现放视频的时候出现了…...

Python常见问题

文章目录 1.python有哪些数据类型2.python中的元组和列表的区别是什么&#xff1f;3.python中的break、continue、pass代表什么意思&#xff1f;4.如何在python中生成一个随机数&#xff1f;5.Python有哪些常见的内置函数&#xff1f;6.请用自己最擅长的编程语言&#xff0c;将…...

小程序 存存上下滑动的页面

推荐阅读文档&#xff1a; Vue3组合式API之getCurrentInstance详解 - 且行且思 - 博客园Vue2中&#xff0c;可以通过this来获取当前组件实例&#xff1b; Vue3中&#xff0c;在setup中无法通过this获取组件实例&#xff0c;console.log(this)打印出来的值是undefined。 在Vue3…...

更换git位置并在pycharm中重新配置

更新 PyCharm 中的 Git 路径 更新 PyCharm 终端的 Shell 路径 检查环境变量 确保系统环境变量中的 Path 包含了新的 Git 安装路径 &#xff0c;如果使用unins0000自动卸载就不会有旧路径。...

AI世界的崩塌:当人类思考枯竭引发数据生态链断裂

AI世界的崩塌&#xff1a;当人类思考枯竭引发数据生态链断裂 ——论过度依赖AI创作对技术进化的反噬 一、数据生态的恶性循环&#xff1a;AI的“自噬危机” 当前AI模型的训练依赖于人类创造的原始数据——书籍、论文、艺术作品、社交媒体动态等。据统计&#xff0c;2025年全球…...

OkHttp连接池

&#x1f9f0; 调整连接池的核心参数 ✅ 最大空闲连接数&#xff08;maxIdleConnections&#xff09;&#xff1a; 含义&#xff1a;连接池中最多保留的空闲连接数量。默认值&#xff1a;5建议值&#xff1a;10~50&#xff08;视并发量而定&#xff09; ✅ 连接保持时间&…...

哈希表的实现01

文章目录 哈希表的实现01哈希概念直接定址法哈希冲突负载因子将关键字转换为整数 哈希函数除法散列法&#xff1a;乘法散列法&#xff08;了解&#xff09;全域散列法&#xff08;了解&#xff09; 处理哈希冲突&#xff08;开放定址法&#xff09;线性探测&#xff1a;二次探测…...

学习日志06 java

还有四天要去比赛了&#xff0c;能赢吗&#xff1f;逼自己一把。。。&#xff01;&#xff01;加油&#xff01; 1 对比一下java重写还是不重写tostring的区别 1. 不重写 toString() 的情况 java class Point {private int x;private int y;public Point(int x, int y) {th…...

spring中的@MapperScan注解详解

一、核心功能与作用 MapperScan是Spring与MyBatis框架集成时用于批量扫描Mapper接口的核心注解&#xff0c;其主要功能包括&#xff1a; 自动注册Mapper接口 通过指定包路径&#xff0c;Spring会自动扫描该路径下的所有Mapper接口&#xff0c;并将其注册为Spring Bean&#x…...

PYTHON训练营DAY25

BUG与报错 一、try else try:# 可能会引发异常的代码 except ExceptionType: # 最好指定具体的异常类型&#xff0c;例如 ZeroDivisionError, FileNotFoundError# 当 try 块中发生 ExceptionType 类型的异常时执行的代码 except: # 不推荐&#xff1a;捕获所有类型的异常&…...

视频图像压缩领域中 DCT 的 DC 系数和 AC 系数详解

引言 在数字图像与视频压缩领域&#xff0c;离散余弦变换&#xff08;Discrete Cosine Transform, DCT&#xff09;凭借其卓越的能量集中特性&#xff0c;成为JPEG、MPEG等国际标准的核心技术。DCT通过将空域信号映射到频域&#xff0c;分离出DC系数&#xff08;直流分量&…...

YOLO v1:目标检测领域的革命性突破

引言 在计算机视觉领域&#xff0c;目标检测一直是一个核心任务&#xff0c;它不仅要识别图像中的物体类别&#xff0c;还要确定物体的精确位置。传统目标检测方法如R-CNN系列虽然准确率高&#xff0c;但计算复杂度高、速度慢。2016年&#xff0c;Joseph Redmon等人提出的YOLO…...

AI智能体 | 使用Coze一键制作“假如书籍会说话”视频,18个作品狂吸17.6万粉,读书博主新标杆!(附保姆级教程)

目录 一、整体工作流设计 二、制作工作流 2.1 开始节点 2.2 大模型_生成对话文案 2.3 代码_字幕切割 2.4 画板_对话背景 2.5 循环_对话语音01 2.5.1 选择器_2 2.5.2 语音合成02 2.5.3 语音合成03 2.5.4 变量聚合_1 2.5.5 视频合成01 2.6 循环_3 2.6.1 选择器_3 …...

HVV蓝队实战面试题

HVV蓝队实战&#xff0c;防守筹备之“部署蜜罐捕获横向扫描行为”。 蜜罐通过模拟内网脆弱服务&#xff08;如SMB、SSH、数据库端口&#xff09;&#xff0c;诱捕攻击者突破边界后的横向探测行为。 通过监测高频端口扫描、非常规协议请求及非授权IP段遍历&#xff0c;结合多源…...

正则表达式(二)-高级应用_谨慎使用

没事建议别瞎用正则表达式,能让后端处理好的数据,尽量后端处理好,减少前端对数据的处理,保证数据原始的完整性,减少前端耗能。(其实就是懒╮(╯▽╰)╭) 1. 分组捕获 分组捕获用于提取匹配的子字符串,使用 () 定义分组。 示例:提取日期中的年、月、日 (\d{4})-(\d{2…...

在K8S集群中部署EFK日志收集

目录 引言环境准备安装自定义资源部署ElasticsearchMaster 节点与 Data 节点的区别生产优化建议安装好以后测试ES是否正常部署Fluentd测试filebeat是否正常推送日志部署Kibana获取账号密码&#xff0c;账号是&#xff1a;elastic集群测试 引言 系统版本为 Centos7.9内核版本为…...

解决常见数据库问题:保障数据安全与稳定的全方位指南

本文结合行业最佳实践与前沿技术&#xff0c;系统性总结数据库运维中的核心问题与解决方案&#xff0c;助力开发者构建高可靠、高性能的数据服务&#xff09; 一、性能优化&#xff1a;从SQL到架构的全面调优 性能问题是数据库运维中最常见的挑战&#xff0c;直接影响用户体验…...

武汉科技大学人工智能与演化计算实验室许志伟课题组参加2025中国膜计算论坛

武汉科技大学人工智能与演化计算实验室许志伟课题组参加2025中国膜计算论坛 2025年5月9日至11日&#xff0c;第五届中国膜计算论坛&#xff08;CWMC 2025&#xff09;在成都信息工程大学隆重召开。会议由 国际膜计算学会&#xff08;IMCS&#xff09; 主办&#xff0c;汇聚了来…...

Femap许可硬件绑定

在电磁仿真领域&#xff0c;Femap软件因其卓越的性能和广泛的应用场景而备受用户青睐。为了确保软件的安全与稳定运行&#xff0c;Femap提供了许可硬件绑定的功能。本文将详细介绍Femap许可硬件绑定的概念和优势&#xff0c;帮助您了解并充分利用这一功能&#xff0c;确保软件在…...

构建优雅对象的艺术:Java 建造者模式的架构解析与工程实践

一、建造者模式的本质与核心价值 在面向对象的软件设计中&#xff0c;创建复杂对象一直是一个需要精心处理的问题。当一个对象的构建需要多个步骤&#xff0c;并且这些步骤具有不同的组合方式时&#xff0c;传统的构造函数方式会显得力不从心。建造者模式&#xff08;Builder …...

vim启动的时候,执行gg

在 Vim 编辑器中&#xff0c;gg 命令是一个非常有用的命令&#xff0c;它可以将光标快速移动到当前窗口的顶部&#xff08;即第一行&#xff09;。如果你想在 Vim 启动时自动执行 gg 命令&#xff0c;有几种方法可以实现这一点&#xff1a; 方法 1&#xff1a;使用 Vim 的启动…...

【SSL部署与优化​】​​HTTP/2与HTTPS的协同效应

HTTP/2与HTTPS的协同效应&#xff1a;为何HTTP/2强制要求TLS 1.2&#xff1f; HTTP/2是HTTP协议的现代升级版&#xff0c;旨在通过多路复用、头部压缩等技术提升性能。然而&#xff0c;HTTP/2的设计与部署与HTTPS&#xff08;TLS加密&#xff09;紧密相关&#xff0c;甚至强制…...

JavaScript篇:揭秘函数式与命令式编程的思维碰撞

大家好&#xff0c;我是江城开朗的豌豆&#xff0c;一名拥有6年以上前端开发经验的工程师。我精通HTML、CSS、JavaScript等基础前端技术&#xff0c;并深入掌握Vue、React、Uniapp、Flutter等主流框架&#xff0c;能够高效解决各类前端开发问题。在我的技术栈中&#xff0c;除了…...

ubuntu24.04上安装NVIDIA driver+CUDA+cuDNN+Anaconda+Pytorch

一、NVIDIA driver 使用Ubuntu系统的&#xff1a;软件和更新——>附加驱动&#xff0c;安装NVIDIA驱动。 二、CUDA 安装命令&#xff1a;sudo apt install nvidia-cuda-toolkit 三、cuDNN cuDNN 9.10.0 Downloads | NVIDIA Developer 四、Anaconda Download Anaconda Di…...

vue3基础学习(上) [简单标签] (vscode)

目录 1. Vue简介 2. 创建Vue应用 2.1 下载JS文件 2.2 引用JS文件 2.3 调用Vue方法​编辑 2.4 运行一下试试: 2.5 代码如下 3.模块化开发模式 3.1 Live Server插件 3.2 运行 4. 常用的标签 4.1 reactive 4.1.1 运行结果 4.1.2 代码: 4.2 ref 4.2.1 运行结果 4.2.2…...

.Net HttpClient 使用代理功能

HttpClient 使用代理功能 实际开发中&#xff0c;HttpClient 通过代理访问目标服务器是常见的需求。 本文将全面介绍如何在 .NET 中配置 HttpClient 使用代理&#xff08;Proxy&#xff09;功能&#xff0c;包括基础使用方式、代码示例、以及与依赖注入结合的最佳实践。 注意…...

深入理解Java适配器模式:从接口兼容到设计哲学

引言&#xff1a;接口不兼容的困局 在软件开发中&#xff0c;我们经常遇到这样的场景&#xff1a; 旧系统有一个「RS232串口设备」&#xff08;仅支持sendByRS232(String data)方法&#xff09;&#xff0c;新系统需要通过「USB接口」&#xff08;要求sendByUSB(String data)…...

非异步信号安全函数

这个程序演示了如何使用sigaction来捕获和处理信号&#xff08;特别是SIGINT&#xff0c;即CtrlC&#xff09;。以下是关键点和潜在问题的分析&#xff1a; 程序功能 信号捕获&#xff1a;注册自定义处理函数handler来捕获信号2&#xff08;SIGINT&#xff0c;通常由CtrlC触发…...

PHP黑白胶卷底片图转彩图功能 V2025.05.15

关于底片转彩图 传统照片底片是摄影过程中生成的反色图像&#xff0c;为了欣赏照片&#xff0c;需要通过冲印过程将底片转化为正像。而随着数字技术的发展&#xff0c;我们现在可以使用数字工具不仅将底片转为正像&#xff0c;还可以添加色彩&#xff0c;重现照片原本的色彩效…...

【C++ / STL】封装红黑树实现map和set

文章目录 一. 源码及框架分析1.决定搜索类型的传参思考&#xff1a;为什么要传第一个参数 2.KeyOfValue的作用 二. 模拟实现map和set1. 实现出复用红黑树框架,并支持insert2. 支持iterator的实现iterator实现思路分析【iterator操作实现详解】 3.支持map的[ ]操作4.map和set代码…...

记录: Windows下远程Liunx 系统xrdp 用到的一些小问题(免费踩坑 记录)

采用liunx Ubuntu22.04版本以下&#xff0c;需要安装 xrdp 或者VNC 具体过程就是下载 在linux命令行里 首先更新软件包&#xff1a;sudo apt update 安装xrdp服务&#xff1a;sudo apt install xrdp 启动XRDP&#xff1a;sudo systemctl start xrdp&#xff08;如果在启动的…...

WordPress 文章和页面:它们的区别是什么?

很多刚接触WordPress的用户&#xff0c;在创建网站内容时往往会遇到这样一个问题&#xff1a;“我应该用‘文章’还是‘页面’&#xff1f;”虽然两者都能发布内容&#xff0c;但它们之间到底有什么区别呢&#xff1f;这篇文章将从易于理解的角度&#xff0c;帮助大家厘清WordP…...