Spring 生态周报速览:2026 年 5 月下旬值得关注的变化

2026-05-26 31 预计阅读时间:1 分钟
来源:spring.io AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:8 分钟

Spring 的每周 roundup 是追踪生态演进节奏的好窗口。即便单周没有重磅版本发布,社区里持续涌出的新工具、配置改进和最佳实践更新,累积起来也在重塑日常开发方式。这篇整理把近期值得留意的方向拎出来,并附上可以直接拿去改造的实操示例。

Spring Boot 启动性能的持续打磨

Spring Boot 的启动耗时一直是微服务和容器化场景下的敏感指标。近几个版本的改动方向很明确:减少 Bean 初始化的阻塞点、延迟不必要的自动配置加载、以及更细粒度的条件评估缓存。

对开发者来说,最直接的收益来自 lazy initialization并行 Bean 初始化 两个开关。前者在 2.2 引入,后者在 3.2 之后逐步成熟。两者组合使用时,冷启动时间在中等规模项目里可以压缩 30%-50%,但代价是首次请求可能触发延迟加载的延迟抖动。

可以这样实践——在 application.yml 中同时开启:

spring:
  main:
    lazy-initialization: true
  boot:
    startup:
      parallel-bean-initialization:
        enabled: true
        max-parallel: 4   # 根据 CPU 核数调整,别超过可用核心

注意:lazy-initialization: true 意味着所有单例 Bean 不再在启动阶段创建,而是等到首次注入或调用时才实例化。如果你的应用有定时任务或启动后必须立即就绪的健康检查端点,需要把相关 Bean 标记为 @Lazy(false) 接口显式排除延迟。

GraalVM Native Image 的生态适配进度

Native Image 编译在 Spring 生态里的推进速度比很多人预期的更快。Spring Framework 6.x 和 Spring Boot 3.x 从架构层面做了大量原生兼容改造:移除运行时字节码生成依赖、提前解析代理配置、将资源路径写进 reachability metadata。

目前大多数主流 Starter 已经提供了 native hint,但第三方库的适配仍然是主要卡点。如果你在项目中用了尚未提供 hint 的库,需要自己补充 reachability metadata。

一个典型的补充方式——为 Jackson 序列化某个不在自动扫描范围内的 DTO:

import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;

public class MyDtoHints implements RuntimeHintsRegistrar {

    @Override
    public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
        // 让 Native Image 编译时知道这个类会被反射访问
        hints.reflection()
             .registerType(TypeReference.of("com.example.dto.OrderResponse"),
                 hint -> hint.withMembers(MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS,
                                          MemberCategory.INVOKE_PUBLIC_METHODS));

        // 如果涉及资源文件读取
        hints.resources()
             .registerPattern("my-config/*.json");
    }
}

然后在 spring.factories 或 Spring Boot 3.x 的 META-INF/spring/aot.factories 中注册:

org.springframework.aot.hint.RuntimeHintsRegistrar=com.example.config.MyDtoHints

编译和验证命令:

# 使用 Spring Boot 的 native 编译插件(需安装 GraalVM JDK)
./mvnw -Pnative native:compile

# 直接运行生成的二进制
./target/my-app

# 对比 JVM 模式的启动时间
./mvnw spring-boot:run

实测中,一个包含 5 个 REST 端点的中等项目,JVM 模式冷启动约 2.8 秒,Native Image 约 0.06 秒。但编译耗时 2-4 分钟,内存占用也更固定——适合短生命周期容器和 Serverless 场景,不适合长时间运行且需要动态类加载的传统服务。

Spring Security 的配置简化趋势

Spring Security 的 Java 配置方式从 WebSecurityConfigurerAdapter 淬变到组件式 SecurityFilterChain Bean 已经是既定事实。近期的变化更偏向 方法级安全的细粒度控制OAuth2/OIDC 集成的开箱即用度

一个实用的模式:用 @PreAuthorize 结合自定义 SecurityExpression 方法,把权限判断从硬编码角色名解放出来:

@Configuration
@EnableMethodSecurity
public class SecurityConfig {

    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll()
                .anyRequest().authenticated())
            .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));
        return http.build();
    }
}

// 自定义表达式根,注入到 Security 评估上下文
@Component("perm")
public class PermissionEvaluator {

    private final OrderRepository orders;

    public PermissionEvaluator(OrderRepository orders) {
        this.orders = orders;
    }

    /** 判断当前用户是否是订单的所有者 */
    public boolean ownsOrder(Long orderId) {
        String currentUser = SecurityContextHolder.getContext()
                .getAuthentication().getName();
        return orders.findById(orderId)
                .map(order -> order.getOwner().equals(currentUser))
                .orElse(false);
    }
}

Controller 中直接调用:

@RestController
@RequestMapping("/orders")
public class OrderController {

    @GetMapping("/{id}")
    @PreAuthorize("@perm.ownsOrder(#id)")
    public OrderResponse getOrder(@PathVariable Long id) {
        // 只有订单所有者能访问,不需要在 URL 匹配层硬写角色
        return orderService.findById(id);
    }
}

这种模式比在 HttpSecurity 里堆 requestMatchers 更灵活,也更容易做单元测试——PermissionEvaluator 是普通 Spring Bean,可以脱离 Security 上下文独立测试逻辑。

Observability:从 Micrometer Tracing 到 OpenTelemetry 的对齐

Spring Boot 3.x 把分布式追踪从 Spring Cloud Sleuth 迁移到 Micrometer Tracing + OpenTelemetry SDK,这是很多人迁移时踩坑的地方。关键变化:Sleuth 的 spring.sleuth.* 配置全部失效,需要改用 management.tracing.* 和 OTel SDK 的原生配置。

一个最小可用的 OTel + Zipkin 导出配置:

management:
  tracing:
    sampling:
      probability: 1.0   # 开发环境全采样,生产环境降到 0.1
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus

otel:
  exporter:
    otlp:
      endpoint: http://localhost:4317   # OTLP gRPC receiver
  resource:
    attributes:
      service.name: my-order-service

依赖变更(Maven):

<!-- 移除 sleuth,替换为 micrometer + otel -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
<!-- Zipkin 用 OTLP 协议对接,不再需要专门的 zipkin sender -->

本地验证:

# 启动 Zipkin(支持 OTLP ingestion)
docker run -d -p 9411:9411 -p 4317:4317 openzipkin/zipkin-otel

# 启动应用后访问任意端点
curl http://localhost:8080/orders/1

# 在 Zipkin UI 查看追踪
open http://localhost:9411

实用检查清单

在跟进 Spring 生态更新时,以下几项值得每次 roundup 后快速扫一遍:

检查项 为什么重要
Boot 版本的 spring.main.lazy-initialization 和并行初始化开关 直接影响冷启动,容器调度场景敏感
项目中第三方库的 Native Image hint 覆盖情况 决定能否顺利编译 native 二进制
@PreAuthorize / @PostAuthorize 的使用是否还依赖废弃 API 方法级安全是当前推荐方式
Sleuth → Micrometer Tracing 的迁移是否完成 Boot 3.x 不再维护 Sleuth
spring.factoriesAutoConfiguration.imports 的迁移 3.x 自动配置注册机制已切换

Spring 的演进节奏是"小步快跑"式的——单个版本改动不大,但方向一致。每周花 10 分钟扫 roundup,比半年后被迫批量迁移要轻松得多。


相关推荐