【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为例:
-
创建Bean A
-
实例化A:调用A的构造函数创建对象(此时对象未填充属性,未初始化)。
-
将A的工厂对象放入三级缓存(singletonFactories),用于后续生成早期引用。
-
填充A的属性:发现需要注入B。
-
-
创建Bean B
-
实例化B:调用B的构造函数创建对象。
-
将B的工厂对象放入三级缓存。
-
填充B的属性:发现需要注入A。
-
-
解决B对A的依赖
-
从三级缓存中获取A的工厂对象(singletonFactories),生成A的早期引用(通过getEarlyBeanReference方法)。
这一步是整合了第一步那个实例化但是没在任何缓存里的A对象,给他变成了半成品代理对象(如果A有被代理的话)
-
将A的早期引用存入二级缓存(earlySingletonObjects),并从三级缓存中删除A的工厂。
-
将A的早期引用注入到B中,完成B的属性填充和初始化。
-
将初始化后的B存入一级缓存(singletonObjects)。
-
-
完成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能解决循环依赖问题吗?
在一定程度上是能解决的
-
Spring 创建 A 时,发现它依赖 B,但 B 被标记为 @Lazy。
-
不立即初始化 B,而是注入一个 B 的代理对象(由 Spring 动态生成)。
-
当 A 的方法首次调用 b.xxx() 时,代理对象才会触发 B 的实际初始化。
-
此时 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 常用的两种配置文件是什么?
application.properties
采用标准的JavaProperties文件格式,即键值对(key=value)的形式,每一行定义一个配置项。
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
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 容器,每个容器都拥有自己的定时任务调度器,并独立地根据
配置的时间触发任务,互不干扰。如果多个节点的配置相同,就会导致同一任务在多个节点上并发执行。
这种情况不仅浪费资源,还可能导致数据不一致、资源竞争等问题,最终导致业务逻辑错误,例如重复处
理相同的数据、发送重复的通知。
解决方法:
- 分布式锁
- 分布式任务调度工具,如XXL-JOB
23. 你的项目是如何统一返回结果的?
code
: 状态码,遵循HTTP状态码规范并扩展业务状态码
message
: 对状态的描述信息
data
: 实际返回的业务数据
timestamp
: 响应时间戳
- 手动显式封装
@GetMapping("/{id}")public Result<User> getUser(@PathVariable Long id) {User user = userService.getUserById(id);return Result.success(user);}
- 自动封装
@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 的主要优点?
-
显著提升开发效率
:Spring Boot 通过自动配置、起步依赖(Starters)和其他开箱即用的功能,极大地减少了项目初始化、配置编写和样板代码的工作量,使开发者能更快地构建和交付应用。 -
与 spring 生态系统的无缝集成
:作为 Spring 家族的一员,Spring Boot 能够方便地整合 Spring 框架下的其他成熟模块(如 Spring Data、Spring Security、Spring Batch 等),充分利用 Spring 强大的生态系统,简化整合工作。 -
强大的自动配置能力
:遵循“约定优于配置”的原则,Spring Boot 能够根据项目依赖自动配置大量
的常见组件(如数据源、Web 容器、消息队列等),提供合理的默认设置。同时也允许开发者根据需
要轻松覆盖或定制配置,极大减少了繁琐的手动配置工作。 -
内嵌 Web 服务器支持
:Spring Boot 自带内嵌的 HTTP服务器(如 Tomcat、Jetty),开发者可以像运行普通 Java 程序一样运行 Spring Boot 应用程序,极大地简化了开发和测试过程。 -
适合微服务架构
:Spring Boot 使得每个微服务都可以独立运行和部署,简化了微服务的开发、测试和运维工作,成为构建微服务架构的理想选择。 -
提供强大的构建工具支持
: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 中读取配置信息?
- 使用
@Value
注解
// 直接注入配置项,支持默认值(如未配置则使用默认值)@Value("${book.author:defaultAuthor}")private String author;
- 使用
@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;
}
- 使用
Environment
接口
@Autowiredprivate Environment env;public String getAppInfo() {String appName = env.getProperty("app.name");String maxRetry = env.getProperty("app.max-retry", "defaultRetry");}
28. Spring 事务中哪几种事务传播行为?
总共有7种,常用的就前两种
PROPAGATION_REQUIRED(默认)
如果当前存在事务,则加入该事务;否则新建一个事务。
所有嵌套方法共享同一个事务,任一方法抛出异常会导致整个事务回滚。PROPAGATION_REQUIRES_NEW
无论当前是否存在事务,都新建一个独立事务。
内层事务与外层事务完全隔离,外层事务回滚不影响内层事务。PROPAGATION_NESTED
如果当前存在事务,则在当前事务内嵌套一个子事务;否则创建新事务。
子事务是父事务的一部分,但可以独立回滚。
子事务回滚不影响父事务(需捕获异常),父事务回滚则子事务也会回滚。PROPAGATION_MANDATORY
必须在一个已存在的事务中运行,否则抛出异常。PROPAGATION_SUPPORTS
如果当前存在事务,则加入该事务;否则以非事务方式运行。PROPAGATION_NOT_SUPPORTED
以非事务方式运行,如果当前存在事务则挂起。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 如何做请求参数校验?
验证请求体
在 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("用户创建成功");
}
验证请求参数
直接在方法参数上使用校验注解:
@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 如何实现异步处理?
主要有四种方式来实现异步处理:
- 使用 @Async注解
- 使用 CompletableFuture
- 使用@Scheduled注解
- 使用线程池
34. 说说对 Spring 中事件机制的理解?
Spring 的事件机制是一种基于观察者模式设计的解耦通信方式,允许组件在特定动作发生时通过事件传递信息,而不必直接依赖彼此。开发者可以自定义继承 ApplicationEvent 的事件类,由事件发布者通过 ApplicationEventPublisher 触发事件,而监听者通过实现 ApplicationListener 接口或使用 @EventListener 注解来捕获并处理事件。这种机制默认以同步方式运行,但结合 @Async 或自定义线程池可支持异步处理,提升系统响应能力。例如,用户注册成功后发布事件,由监听器异步发送邮件或初始化数据,避免主流程阻塞。
35. Spring 中如何配置多数据源?
一文带你理清SpringBoot如何实现多数据源动态路由【全干货,无废话】
36. Spring 中有哪些设计模式?
工厂模式(Factory Pattern)
作用:隐藏对象创建细节,由容器统一管理 Bean 的生命周期。单例模式(Singleton Pattern)
Spring 默认的 Bean 作用域为单例(singleton),确保每个容器中一个 Bean 仅有一个实例。
作用:节省资源,保证全局一致性。原型模式(Prototype Pattern)
Bean 的作用域设为 prototype 时,每次请求都会创建新实例(如 @Scope(“prototype”))。代理模式(Proxy Pattern)
Spring AOP(面向切面编程)通过动态代理实现横切关注点(如事务、日志)。模板方法模式(Template Method Pattern)
JdbcTemplate、RestTemplate 等模板类封装通用流程,消除重复代码观察者模式(Observer Pattern)
核心应用:Spring 事件驱动模型(ApplicationEvent 和 ApplicationListener)。适配器模式(Adapter Pattern)
统一接口,兼容不同实现。装饰者模式(Decorator Pattern)
HttpServletRequestWrapper 包装 HTTP 请求,增强其行为(如缓存请求体)。策略模式(Strategy Pattern)
Spring MVC 的 HandlerMapping 根据请求匹配不同策略的处理器。委派模式(Delegate Pattern)
DispatcherServlet 将请求分发给不同的处理器(如 Controller、Handler)。建造者模式(Builder Pattern)
分步构建复杂对象。责任链模式(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是什么关系?2. 谈一谈对Spring IoC的理解3. Component 和 Bean 的区别?4. Autowired 和 Resource 的区别?5. 注入Bean的方法有哪些?6. 为什么Spring 官方推荐构造函数注入?…...
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事件驱动架构的核心实现策略
文章目录 🎯 观察者模式(Observer Pattern)深度解析一、模式本质与核心价值二、经典UML结构三、Unity实战代码(玩家血量监控系统)1. 定义观察者接口与主题基类2. 实现具体主题(玩家血量)3. 实现…...
Java基础语法之数组
数组 一、认识数组 1.什么是数组 数组就是一个容器,用来存一批同种类型的数据。 举例 20, 10, 80, 60, 90 int[] arr {20, 10, 80, 60, 90};张三, 李四, 王五 String[] names {"张三", "李四", "王五"};2.为什么要使用数组 假设…...
Vue3学习(组合式API——计算属性computed详解)
目录 一、计算属性computed。 Vue官方提供的案例。(普通写法与计算属性写法) 使用计算属性computed重构——>简化描述响应式状态的复杂逻辑。 (1)计算属性computed小案例。 <1>需求说明。(筛选原数组——>得新数组) &…...
高海拔和远距离的人员识别:面部、体型和步态的融合
大家读完就觉得有帮助记得关注和点赞!!! 摘要 我们解决了在无约束环境中进行全身人体识别的问题。这个问题出现在诸如IARPA高空和远距离生物识别与身份识别(BRIAR)计划等监视场景中,其中生物识别数据是在长…...
《P2345 [USACO04OPEN] MooFest G》
题目背景 P5094 [USACO04OPEN] MooFest G 加强版 题目描述 约翰的 n 头奶牛每年都会参加“哞哞大会”。 哞哞大会是奶牛界的盛事。集会上的活动很多,比如堆干草,跨栅栏,摸牛仔的屁股等等。 它们参加活动时会聚在一起,第 i 头…...
浅浅学:DoIP工作流程及基于DoIP的诊断/刷写工具
注:阅读本文需要对UDS及BootLoader有一定了解,基础内容不做赘述。 在汽车"新四化"浪潮的推动下,智能座舱、自动驾驶、车路协同等创新技术正加速重构行业格局。随着车载ECU数量突破百个量级,软件代码量呈指数级增长——…...
首个专业AI设计Agent发布-Lovart
Lovart是什么 Lovart 是为设计师打造的世界上首个专业设计 Agent。Lovart 能像专业设计师一样思考和执行设计任务,提供高水平的设计方案。基于自然语言交互,用户能快速调整布局、颜色和构图。Lovart 支持从创意拆解到专业交付的全链路设计,单…...
二叉树(中序遍历)
嘿,欢迎来到小巫blog!小巫又来啦!看到你对二叉树中序遍历这道题有点困惑,别担心,我会一步步带你搞定它!这道题是树的基础题目,掌握了它,你对树的遍历就会有很深的理解。我相信&#…...
Ubuntu 系统默认已安装 python,此处只需添加一个超链接即可
步骤 1:确认 Python 3 的安装路径 查看当前 Python 3 的路径: which python3 输出类似: /usr/bin/python3 步骤 2:创建符号链接 使用 ln -s 创建符号链接,将 python 指向 python3: sudo ln -s /usr/b…...
AcroForm JavaScript Promise 对象应用示例: 异步加载PDF文件
这段代码演示了在Adobe Acrobat DC Pro 的 JavaScript 环境中如何使用 Promise 对象处理异步操作。具体功能是: 定义了一个loadFile函数,模拟异步加载PDF文件的操作使用Promise对象封装异步操作,提供成功(resolve)和失败(reject)两种状态通过…...
LeetCode 热题 100 114. 二叉树展开为链表
LeetCode 热题 100 | 114. 二叉树展开为链表 大家好,今天我们来解决一道经典的二叉树问题——二叉树展开为链表。这道题在 LeetCode 上被标记为中等难度,要求将二叉树展开为一个单链表,展开后的单链表应该与二叉树的先序遍历顺序相同。 问题…...
DML和DQL
1. 设置MySQL的储存引擎 上一章的附录里已经将ini设置好了,不用再次设置 2. DML语句 插入单数据记录 插入多数据记录 将查询结果插入新表 更新数据 删除数据 注意:delete删除只会删除数据,不会重置表的现有逻辑,truncate会重置表逻…...
多线程与线程互斥
我们初步学习完线程之后,就要来试着写一写多线程了。在写之前,我们需要继续来学习一个线程接口——叫做线程分离。 默认情况下,新创建的线程是joinable的,线程退出后,需要对其进行pthread_join操作,否则无法…...
BMS工具箱用来执行贝叶斯模型平均(BMA)计算模块
贝叶斯模型平均(Bayesian Model Averaging,BMA)是一种用于处理模型不确定性的统计方法,通过结合多个模型的预测结果来提高预测的准确性和鲁棒性。在 MATLAB 中,可以使用专门的工具箱(如 BMS 工具箱…...
Java死锁排查:线上救火实战指南
想象一下,你正在值班,突然监控告警红成一片,用户反馈雪花般飘来:“系统卡死了!用不了了!” —— 这很可能就是Java应用遭遇了“死锁”这个大魔王。这时候,你就是救火队长,首要任务不…...
第十九次博客打卡
今天学习的内容是Java中的常见循环。 在 Java 中,常见的循环结构主要有以下几种:for 循环、while 循环、do-while 循环以及增强型 for 循环(也称为 for-each 循环)。 1. for 循环 for 循环是一种非常灵活的循环结构,…...
智能体制作学习笔记1——智能体
01 智能体_哔哩哔哩_bilibili 大语言模型可以理解成一个很厉害的人。 但是要完成一些特定的工作,除了大语言模型,还需要一些工具和业务流程,这样才能自动化帮我们完成特定的工作,这个就叫做智能体。 突然发现放视频的时候出现了…...
Python常见问题
文章目录 1.python有哪些数据类型2.python中的元组和列表的区别是什么?3.python中的break、continue、pass代表什么意思?4.如何在python中生成一个随机数?5.Python有哪些常见的内置函数?6.请用自己最擅长的编程语言,将…...
小程序 存存上下滑动的页面
推荐阅读文档: Vue3组合式API之getCurrentInstance详解 - 且行且思 - 博客园Vue2中,可以通过this来获取当前组件实例; Vue3中,在setup中无法通过this获取组件实例,console.log(this)打印出来的值是undefined。 在Vue3…...
更换git位置并在pycharm中重新配置
更新 PyCharm 中的 Git 路径 更新 PyCharm 终端的 Shell 路径 检查环境变量 确保系统环境变量中的 Path 包含了新的 Git 安装路径 ,如果使用unins0000自动卸载就不会有旧路径。...
AI世界的崩塌:当人类思考枯竭引发数据生态链断裂
AI世界的崩塌:当人类思考枯竭引发数据生态链断裂 ——论过度依赖AI创作对技术进化的反噬 一、数据生态的恶性循环:AI的“自噬危机” 当前AI模型的训练依赖于人类创造的原始数据——书籍、论文、艺术作品、社交媒体动态等。据统计,2025年全球…...
OkHttp连接池
🧰 调整连接池的核心参数 ✅ 最大空闲连接数(maxIdleConnections): 含义:连接池中最多保留的空闲连接数量。默认值:5建议值:10~50(视并发量而定) ✅ 连接保持时间&…...
哈希表的实现01
文章目录 哈希表的实现01哈希概念直接定址法哈希冲突负载因子将关键字转换为整数 哈希函数除法散列法:乘法散列法(了解)全域散列法(了解) 处理哈希冲突(开放定址法)线性探测:二次探测…...
学习日志06 java
还有四天要去比赛了,能赢吗?逼自己一把。。。!!加油! 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接口的核心注解,其主要功能包括: 自动注册Mapper接口 通过指定包路径,Spring会自动扫描该路径下的所有Mapper接口,并将其注册为Spring Bean&#x…...
PYTHON训练营DAY25
BUG与报错 一、try else try:# 可能会引发异常的代码 except ExceptionType: # 最好指定具体的异常类型,例如 ZeroDivisionError, FileNotFoundError# 当 try 块中发生 ExceptionType 类型的异常时执行的代码 except: # 不推荐:捕获所有类型的异常&…...
视频图像压缩领域中 DCT 的 DC 系数和 AC 系数详解
引言 在数字图像与视频压缩领域,离散余弦变换(Discrete Cosine Transform, DCT)凭借其卓越的能量集中特性,成为JPEG、MPEG等国际标准的核心技术。DCT通过将空域信号映射到频域,分离出DC系数(直流分量&…...
YOLO v1:目标检测领域的革命性突破
引言 在计算机视觉领域,目标检测一直是一个核心任务,它不仅要识别图像中的物体类别,还要确定物体的精确位置。传统目标检测方法如R-CNN系列虽然准确率高,但计算复杂度高、速度慢。2016年,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蓝队实战,防守筹备之“部署蜜罐捕获横向扫描行为”。 蜜罐通过模拟内网脆弱服务(如SMB、SSH、数据库端口),诱捕攻击者突破边界后的横向探测行为。 通过监测高频端口扫描、非常规协议请求及非授权IP段遍历,结合多源…...
正则表达式(二)-高级应用_谨慎使用
没事建议别瞎用正则表达式,能让后端处理好的数据,尽量后端处理好,减少前端对数据的处理,保证数据原始的完整性,减少前端耗能。(其实就是懒╮(╯▽╰)╭) 1. 分组捕获 分组捕获用于提取匹配的子字符串,使用 () 定义分组。 示例:提取日期中的年、月、日 (\d{4})-(\d{2…...
在K8S集群中部署EFK日志收集
目录 引言环境准备安装自定义资源部署ElasticsearchMaster 节点与 Data 节点的区别生产优化建议安装好以后测试ES是否正常部署Fluentd测试filebeat是否正常推送日志部署Kibana获取账号密码,账号是:elastic集群测试 引言 系统版本为 Centos7.9内核版本为…...
解决常见数据库问题:保障数据安全与稳定的全方位指南
本文结合行业最佳实践与前沿技术,系统性总结数据库运维中的核心问题与解决方案,助力开发者构建高可靠、高性能的数据服务) 一、性能优化:从SQL到架构的全面调优 性能问题是数据库运维中最常见的挑战,直接影响用户体验…...
武汉科技大学人工智能与演化计算实验室许志伟课题组参加2025中国膜计算论坛
武汉科技大学人工智能与演化计算实验室许志伟课题组参加2025中国膜计算论坛 2025年5月9日至11日,第五届中国膜计算论坛(CWMC 2025)在成都信息工程大学隆重召开。会议由 国际膜计算学会(IMCS) 主办,汇聚了来…...
Femap许可硬件绑定
在电磁仿真领域,Femap软件因其卓越的性能和广泛的应用场景而备受用户青睐。为了确保软件的安全与稳定运行,Femap提供了许可硬件绑定的功能。本文将详细介绍Femap许可硬件绑定的概念和优势,帮助您了解并充分利用这一功能,确保软件在…...
构建优雅对象的艺术:Java 建造者模式的架构解析与工程实践
一、建造者模式的本质与核心价值 在面向对象的软件设计中,创建复杂对象一直是一个需要精心处理的问题。当一个对象的构建需要多个步骤,并且这些步骤具有不同的组合方式时,传统的构造函数方式会显得力不从心。建造者模式(Builder …...
vim启动的时候,执行gg
在 Vim 编辑器中,gg 命令是一个非常有用的命令,它可以将光标快速移动到当前窗口的顶部(即第一行)。如果你想在 Vim 启动时自动执行 gg 命令,有几种方法可以实现这一点: 方法 1:使用 Vim 的启动…...
【SSL部署与优化】HTTP/2与HTTPS的协同效应
HTTP/2与HTTPS的协同效应:为何HTTP/2强制要求TLS 1.2? HTTP/2是HTTP协议的现代升级版,旨在通过多路复用、头部压缩等技术提升性能。然而,HTTP/2的设计与部署与HTTPS(TLS加密)紧密相关,甚至强制…...
JavaScript篇:揭秘函数式与命令式编程的思维碰撞
大家好,我是江城开朗的豌豆,一名拥有6年以上前端开发经验的工程师。我精通HTML、CSS、JavaScript等基础前端技术,并深入掌握Vue、React、Uniapp、Flutter等主流框架,能够高效解决各类前端开发问题。在我的技术栈中,除了…...
ubuntu24.04上安装NVIDIA driver+CUDA+cuDNN+Anaconda+Pytorch
一、NVIDIA driver 使用Ubuntu系统的:软件和更新——>附加驱动,安装NVIDIA驱动。 二、CUDA 安装命令: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 使用代理功能 实际开发中,HttpClient 通过代理访问目标服务器是常见的需求。 本文将全面介绍如何在 .NET 中配置 HttpClient 使用代理(Proxy)功能,包括基础使用方式、代码示例、以及与依赖注入结合的最佳实践。 注意…...
深入理解Java适配器模式:从接口兼容到设计哲学
引言:接口不兼容的困局 在软件开发中,我们经常遇到这样的场景: 旧系统有一个「RS232串口设备」(仅支持sendByRS232(String data)方法),新系统需要通过「USB接口」(要求sendByUSB(String data)…...
非异步信号安全函数
这个程序演示了如何使用sigaction来捕获和处理信号(特别是SIGINT,即CtrlC)。以下是关键点和潜在问题的分析: 程序功能 信号捕获:注册自定义处理函数handler来捕获信号2(SIGINT,通常由CtrlC触发…...
PHP黑白胶卷底片图转彩图功能 V2025.05.15
关于底片转彩图 传统照片底片是摄影过程中生成的反色图像,为了欣赏照片,需要通过冲印过程将底片转化为正像。而随着数字技术的发展,我们现在可以使用数字工具不仅将底片转为正像,还可以添加色彩,重现照片原本的色彩效…...
【C++ / STL】封装红黑树实现map和set
文章目录 一. 源码及框架分析1.决定搜索类型的传参思考:为什么要传第一个参数 2.KeyOfValue的作用 二. 模拟实现map和set1. 实现出复用红黑树框架,并支持insert2. 支持iterator的实现iterator实现思路分析【iterator操作实现详解】 3.支持map的[ ]操作4.map和set代码…...
记录: Windows下远程Liunx 系统xrdp 用到的一些小问题(免费踩坑 记录)
采用liunx Ubuntu22.04版本以下,需要安装 xrdp 或者VNC 具体过程就是下载 在linux命令行里 首先更新软件包:sudo apt update 安装xrdp服务:sudo apt install xrdp 启动XRDP:sudo systemctl start xrdp(如果在启动的…...
WordPress 文章和页面:它们的区别是什么?
很多刚接触WordPress的用户,在创建网站内容时往往会遇到这样一个问题:“我应该用‘文章’还是‘页面’?”虽然两者都能发布内容,但它们之间到底有什么区别呢?这篇文章将从易于理解的角度,帮助大家厘清WordP…...