Spring Framework 7.0震撼发布!JDK 25支持、GraalVM 25原生、JPA

Spring Framework 7.0正式发布,大幅升级技术栈基线,淘汰过时API,拥抱Jakarta EE 11、JDK 25 LTS、Kotlin 2.2与GraalVM 25,同时强化空安全、HTTP客户端与测试架构,为AI时代基础设施注入新活力。

【一】Spring 7.0:不是小修小补,而是面向未来的全面重构  

各位老铁,今天咱们不聊显卡价格,也不讲英伟达财报,来点真正硬核的——Spring Framework 7.0正式发布了!这不是一次普通的版本迭代,而是一场彻头彻尾的技术栈大换血。如果你还在用javax开头的注解、还在依赖RestTemplate、甚至还在跑Undertow服务器,那恭喜你,你的代码已经进入“遗产系统”倒计时。  

Spring 7.0明确保留JDK 17作为最低基线,但官方强烈推荐直接上JDK 25——这是最新的LTS版本。同时,整个框架全面拥抱Jakarta EE 11,这意味着javax.*包彻底退出历史舞台。此外,Kotlin升级到2.2,GraalVM同步跟进至25版本,并采用全新的“精确可达性元数据”(exact reachability metadata)格式,为原生镜像构建提供更精准的反射与资源提示。  

底层依赖也全线拉高:Servlet 6.1(对应Tomcat 11.0 / Jetty 12.1)、JPA 3.2(Hibernate ORM 7.1/7.2)、Bean Validation 3.1(Hibernate Validator 9.0+)、Netty 4.2,甚至连JUnit都直接跳到6.x。这不是为了炫技,而是为了支撑更大规模、更高并发、更低延迟的AI基础设施——毕竟,今天的模型训练集群动辄上万卡,没个现代化的运行时底座,连PUE都压不住。  

【二】被砍掉的旧时代:这些API和服务器,请彻底告别  

Spring团队这次下手非常狠。首先,spring-jcl模块被彻底移除,转而依赖Apache Commons Logging 1.3.0。好消息是,绝大多数应用无需修改,因为spring-jcl本就是传递依赖,日志调用方式不变。  

更关键的是:javax.annotation 和 javax.inject 包下的所有注解全面失效!包括 @Resource、@PostConstruct、@Inject 等常用注解。如果你还在用这些,必须手动迁移到 jakarta.annotation 和 jakarta.inject 包。别指望兼容层了,Spring 7.0不给你留后路。  

路径匹配的旧选项也全被清理。比如 suffixPatternMatch、trailingSlashMatch、favorPathExtension 等配置,早在6.0就标记为废弃,现在直接删库。内容协商机制中的 PathExtensionContentNegotiationStrategy 也不复存在。  

Undertow?对不起,Servlet 6.1不支持,Spring直接把它从WebSocket和WebFlux底层支持中踢出局。虽然未来Undertow若兼容Servlet 6.1仍可用标准Servlet适配器,但现在只能换Tomcat 11或Jetty 12.1。  

其他被砍的还有:ListenableFuture(请用CompletableFuture)、WebJars-locator-core(换lite版)、OkHttp3支持、以及一堆过时的工具类字段和方法。甚至连HttpComponentsClientHttpRequestFactory的setConnectTimeout方法都被干掉了。  

【三】破而后立:这些破坏性变更,升级前必须检查  

Spring 7.0带来了一些看似细微但实则致命的破坏性变更。首当其冲的是SpringExtension在JUnit Jupiter中的作用域调整。现在,每个测试方法拥有独立的ExtensionContext,这虽然让@Nested嵌套测试类的依赖注入更一致,但可能导致你的TestExecutionListener失效。  

如果你的@Nested测试类在升级后突然崩了,赶紧在顶级类上加上:  
@SpringExtensionConfig(useTestClassScopedExtensionContext = true)  

如果你自定义了TestExecutionListener并重写了prepareTestInstance,现在要从testContext.getTestInstance().getClass()获取当前测试类,而不是testContext.getTestClass()。文档已更新,务必重读。  

另一个重大变化是HttpHeaders。它不再继承MultiValueMap!因为HTTP头本质上是大小写不敏感的键值对集合,很多Map操作既不符合语义又性能差。因此,HttpHeaders#asMultiValueMap等方法已被标记为立即废弃。建议改用其他专用方法处理头信息。  

【四】官方“劝退”名单:这些技术已被标记为过时  

别抱侥幸心理了!Spring 7.0明确宣布:RestTemplate 已“功能冻结”,官方文档已将其标记为过时,7.1版本将正式加上@Deprecated注解。建议全面转向WebClient或新的RestClient。  

Spring MVC的 XML命名空间也正式过时,虽暂不删除,但不再跟随Java配置演进。其他如等核心命名空间不受影响。  

Kotlin脚本模板支持因Kotlin团队计划移除JSR-223而被废弃。JUnit 4在Spring TestContext中的支持同样过时,SpringRunner、AbstractJUnit4SpringContextTests等类全部进入淘汰名单。  

Jackson 2.x?抱歉,已过时。Spring 7.0默认支持Jackson 3.x(包名变为tools.jackson),2.x将在7.1禁用自动检测,7.2彻底移除。注意:Jackson2ObjectMapperBuilder没有3.x等价物,改用JsonMapper.builder()。  

PathMatcher在Spring MVC中也被标记废弃,推荐使用PathPattern。连HandlerMappingIntrospector SPI(用于Spring Security路径对齐)也过时了。  

此外,XLS、RSS、PDF等视图类(如AbstractXlsView)全部废弃,未来将移出Spring,建议直接引入独立库并在Handler中手动渲染。  

【五】空安全革命:从JSR-305到JSpecify,类型系统全面升级  

Spring团队终于把空安全注解从饱受争议的JSR-305迁移到JSpecify。为什么?因为JSpecify有明确规范、无split-package问题、工具链完善、与Kotlin无缝集成,还能标注泛型、数组、变参的可空性。  

这意味着Spring Framework自身代码现在能精准表达“这个List里的每个元素都非空”或“这个Optional可能为空但值非空”等复杂语义。强烈建议你的项目也采用JSpecify,以构建真正null-safe的应用。  

【六】新武器登场:JmsClient、RestTestClient、API版本控制  

Spring 7.0延续了6.1的“Client化”趋势,推出JmsClient,提供简洁的send/receive API,替代JmsMessagingTemplate。类似地,JdbcClient也增强,支持fetch size、max rows、query timeout等细粒度控制。  

社区翘首以盼的RestTestClient终于来了!它是WebTestClient的非响应式版本,支持绑定真实服务器、@Controller或ApplicationContext,提供流畅的断言API,测试体验拉满。  

API版本控制首次获得官方支持!无论Spring MVC还是WebFlux,现在都能基于请求头、参数或媒体类型解析API版本,标记废弃版本,并通知客户端。RestClient、WebClient甚至HTTP接口客户端都支持设置版本。  

【七】开发者体验爆改:Kotlin协程上下文传播、Optional在SpEL中自动解包  

Kotlin开发者注意!Spring 7.0现在自动为协程传播上下文(如Trace ID)。通过PropagationContextElement操作符,你的协程也能拥有和阻塞/响应式调用一样的分布式追踪能力。  

SpEL表达式对java.util.Optional的支持大幅增强。现在不仅能安全调用方法,还能用Elvis操作符(?:)自动解包,比如:  
#{user?.preferences ?: defaultPrefs}  
如果preferences是Optional,Spring会自动unwrap,无需显式.orElse()。  

【八】GraalVM原生镜像:元数据格式大改,反射注册更简洁  

Spring 7.0全面采用GraalVM社区统一的可达性元数据格式。资源提示从正则表达式改为glob模式。例如:  
旧:/files/*.ext → 匹配/files/a.ext和/files/folder/b.txt  
新:/files/*.ext → 仅匹配/files/a.ext  
要匹配子目录,必须写成/files/**/*.ext。且“排除”规则已移除。  

反射提示也简化:注册一个类型即隐含其方法、构造器、字段的introspection。过去这么写:  
hints.reflection().registerType(MyType.class, MemberCategory.DECLARED_FIELDS);  
现在只需:  
hints.reflection().registerType(MyType.class);  
MemberCategory.PUBLIC_FIELDS等常量已重命名为INVOKE_PUBLIC_FIELDS,意图更清晰。  

【九】数据库与消息队列:JPA 3.2注入更优雅,Hibernate StatelessSession可用  

JPA 3.2支持直接用@Inject/@Autowired注入EntityManagerFactory或共享EntityManager,无需额外定义SharedEntityManagerBean。LocalContainerEntityManagerFactoryBean自动提供带限定符的Bean。  

Hibernate原生支持迁移到orm.jpa.hibernate包,保留LocalSessionFactoryBean、HibernateTransactionManager等核心类,支持SessionFactory#getCurrentSession()。  

更重要的是,LocalSessionFactoryBean现在可注入StatelessSession代理(推荐用Hibernate ORM 7.2),特别适合高吞吐批量写入场景。  

JMS默认DestinationResolver改为SimpleDestinationResolver,会缓存Queue/Topic实例。若需每次解析(极少见),请显式配置DynamicDestinationResolver。  

【十】结语:这不是升级,是基础设施的代际跃迁  

Spring Framework 7.0绝非普通版本更新,它是一次面向AI时代基础设施的系统性重构。从JDK 25到GraalVM原生,从Jakarta EE 11到JPA 3.2,从空安全到协程上下文传播,每一处改动都在为更高密度、更低延迟、更强弹性的计算平台铺路。  

如果你正在构建下一代AI训练集群、液冷数据中心或自研调度系统,Spring 7.0提供的现代化运行时底座,或许是比你想象中更重要的基石。老项目迁移虽有阵痛,但方向已明:向前,别回头。