最新实战案例锦集:《Spring Boot3实战案例合集》持续更新,每天至少更新一篇文章,订阅后将赠送文章最后展示的所有MD文档(学习笔记)。
环境:SpringBoot3.2.5
1. 多线程初始化Bean
在6.2之前的所以版本中Spring 容器在实例化单例Bean时,都是在一个for循环中,一个一个的实例化。自6.2起,单例bean的初始化支持多线程。底层通过Executor + CompletableFuture#runAsync 实现。同时你还可以自定义线程池对象,如下方式:
@Bean
public Executor bootstrapExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(5) ;
taskExecutor.setMaxPoolSize(5) ;
taskExecutor.initialize() ;
return taskExecutor ;
}
注意:bean的名称必须是bootstrapExecutor。
2. 新增注解@Fallback
当Spring容器中存在多个相同类型的Bean,并且需要确定在自动装配时应该使用哪个Bean时,@Primary注解就非常有用了,否则容器都无法正确启动。
Spring6.2新增了一个@Fallback注解,该注解表示该 bean 符合备用自动装配候选条件,这是 @Primary 注释的替代品。如果多个匹配候选者中只有少数几个被标记为fallback,则剩余的 bean 将被选中。与Primary bean 一样,备用 bean 仅在查找单个注入点的多个候选者时起作用。如下示例:
interface CommonDAO {}
class UserDAO implements CommonDAO {}
class PersonDAO implements CommonDAO {}
public class AppConfig {
public UserDAO userDAO() {
return new UserDAO() ;
}
public PersonDAO personDAO() {
return new PersonDAO() ;
}
public CommonService commonService(CommonDAO dao) {
return new CommonService(dao) ;
}
}
在该示例中,CommonService注入的是UserDAO。当UserDAO Bean不存在时,才会注入PersonDAO。
3. @Bean定义2个相同的beanName
先看如下示例:
public class AppConfig {
"a") (name =
Person personA() {
return new Person(1) ;
}
"a") (name =
Person personB() {
return new Person(2) ;
}
}
这里通过@Bean声明2个Person bean对象,但是他们的名称相同。在6.2之前的版本中,容器中存在的将是
4. RestClient改进
RestClient新增了create(URI)方法,直接将URI解析为baseUrl。
改进
public String client() {
return RestClient.create("http://localhost:8080")
.get()
.uri(URI.create("/params/index"))
.retrieve()
.body(String.class) ;
}
以上代码在6.2之前版本,运行后将抛出如下异常:
而在6.2版本开始,以上代码将没有任何问题。
5. 从请求Header中绑定数据
有如下接口:
@GetMapping("/{path}")
public void get(Params params, @PathVariable long path,
@RequestParam String foo, @RequestHeader String accept) {
System.out.printf("path: %d%n", path);
System.out.printf("foo: %s%n", foo);
System.out.printf("accept: %s%n", accept);
System.out.printf("params: %s%n", params);
}
public static record Params(@PathVariable long path,
@RequestParam String foo, @RequestHeader String accept) {}
在6.2之前版本输出结果如下:
自6.2开始record中header值也能正常的绑定了。
6. 任务调度新增跟多元数据信息
目前,/actuator/scheduledtasks actuator 端点提供了关于计划任务的信息,包括任务的类型、目标和调度信息。本次新增了如下信息
上次执行时间
上次执行状态
下次执行时间
7. 其它功能
更新 UndertowHttpHandlerAdapter 以进行调度
优化 @Contract Javadoc 以提及此更改和新的返回值
AOT 处理 Bean 验证时不考虑级联和容器元素约束
避免通过 @Lazy 代理重复解析单例 Bean
注册 @TestBean 完全限定方法名的运行时提示
引入 @DisabledInAotMode 中对自定义原因的支持
在 ResponseBodyEmitter 中尽可能使用乐观锁
修订 WebClient 和 WebTestClient 中使用 Apache HTTP 组件的 Cookie 支持
从 @Contract 中移除纯属性
引入 @CheckReturnValue 注解
如果资源路径不以斜杠结尾,ResourceHttpRequestHandler 抛出 IllegalArgumentException 会导致某些第三方库失效
在 ThreadPoolTaskExecutor 和 ThreadPoolTaskScheduler 上提供虚拟线程的一流选项
如果 @RequestParam 从 null 转换为空字符串,HttpServiceProxyFactory 应该省略可选参数
Reactor Netty 响应不应缓冲完整响应
放宽 MockMVC DSL 构造函数的可见性
支持从 Publisher 转换为 InputStream
验证静态资源位置以斜杠结尾
在 BeanUtils 中支持记录规范构造函数
重命名 OverrideMetadata 用于 Bean 覆盖
重命名 BeanOverrideStrategy 枚举常量
优化 ServletWebRequest
移除静态资源处理中的相对路径支持
为 @MockitoBean 和 @MockitoSpyBean 添加 value 属性别名
拒绝带有工厂前缀的 Bean 名称用于 Bean 覆盖
修订 WhatWG URL 解析器中 URI 变量语法的处理
在 preDetermineBeanTypes 中也检查预注册的单例
移除不必要的数组长度检查
优化 CorsConfiguration
添加 RFC 3986 URL 解析器
在 ReactorServerHttpRequest 中处理由 Reactor-Netty 解析的 X-Forwarded-Prefix
RestClient 应自动检测 ReactorClientHttpRequestFactory
改进 SockJS 支持中的随机源
停止用伪定义替换现有的 Bean 覆盖定义
在 @TestBean 和 @MockitoBean 中引入 enforceOverride 标志
重构 unwrapOptional 方法以提高可读性和性能
ServerSentEvent 应实现 equals() 和 hashCode()
减少因 NoTransactionInContextException 实例引起的 GC 压力
将 DynamicPropertyRegistrarBeanInitializer 设为公共类
改进AbstractBeanDefinition 和 BeanMetadataAttribute 的 toString() 方法
添加用于资源处理器检查的工具方法
UrlHandlerFilter 不应从上下文路径 URL 中删除尾部斜杠
AbstractGenericHttpMessageConverter 没有接受 Charset 的构造函数
JdbcClient ResultQuerySpec 提供 optionalValue() 方法
在 HttpComponentsClientHttpRequestFactory 中添加读取超时设置器
修复由 EclipseLinkJpaDialect 中的同步块导致的虚拟线程固定问题
添加 RestClient.Builder#messageConverters(List)
优化附加 Assert 方法的空安全性
当 @Transactional 传播级别不是 REQUIRES_NEW 或 NOT_SUPPORTED 时,抛出运行时错误
启用虚拟线程时,长时间运行的固定延迟任务会阻塞固定速率任务
提供一种公共机制来检测 AOT 处理是否正在进行
在 JdkClientHttpRequest 中仅使用一种请求超时机制
使用 AOT 和原生镜像支持 Bean 覆盖特性
在 Spring AOT 中限制 BeanInstanceSupplier 中的反射操作
使用 IntroductionInterceptor 创建的 Mixin 导致动态代理而不是 CGLIB 代理
在 ServletServerHttpRequest 中宽松地解析 URI
排除 StompSubProtocolHandler 中的授权消息的 ERROR 日志记录
在 AbstractContextLoaderInitializer 中传播完整的 ServletContext(用于访问 SessionCookieConfig)
以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏
推荐文章
进阶!@ConfigurationProperties注解高级用法你知道吗?
我100%确定,你对@ComponentScan注解的了解仅限于皮毛
Spring Boot中通过3种方式初始化数据,你们如何选择?
基于Spring Boot给所有Controller接口添加统一前缀的5种方式