升级背景
1.技术债与代码规范化
- 原有版本(4.3.0)发布于 2016 年,距今已有多年,依赖的 JDK、第三方库、构建插件等均较为陈旧。
- 历史原因导致部分模块在路径管理、Bean 配置、事务管理等方面存在不规范实现,影响可维护性与可扩展性。
- 升级可借机清理遗留代码、引入统一的编码规范,减少后续维护成本。
2.容器化与服务治理趋势
- 近年来公司服务逐步向容器化和 Kubernetes 环境迁移,对服务的启动速度、健康检查、配置管理等有更高要求。
- Spring 5.x 对响应式编程、WebFlux、Bean 初始化流程等有优化,能更好适配云原生部署环境。
- 与 Spring Boot 2.x / 3.x 的生态配合更好,便于集成微服务治理组件(如 Spring Cloud Alibaba、Service Mesh)。同时也是为老项目转Spring Boot做铺垫
3.安全与依赖更新
- Spring 4.3.0 已停止社区支持,存在未修复的安全漏洞。
- 升级至 5.3.39 能获取官方安全补丁和长期支持(LTS)版本的保障。
- 可同时升级依赖的 Jackson、Tomcat、Hibernate 等核心组件,提升安全性与性能。
4.为未来的 AI 智能体趋势做准备
- 随着 AI 大模型和智能体技术在业务系统中的应用增多,后端框架需要具备更好的异步处理、事件驱动能力以及与 AI 服务的集成能力。
- Spring 5.x 的响应式 API、WebFlux、函数式编程支持,为未来接入 AI Agent、实时流式处理(如 RAG、实时推理)提供了基础设施。
- 通过升级可提前构建面向未来的可扩展架构,避免 AI 应用落地时因框架过旧而受限。
升级前准备
- 项目依赖路径梳理 1.这种升级需要从最前端的工程开始,避免因依赖传递导致其他工程产生spring版本冲突控制项目风险; 2.项目内Dependency Analyzer 梳理引用的旧版本spring组件
升级过程中遇到的坑
1. 项目启动报错
org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] for bean with name 'org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping#0'....nested exception is java.lang.ClassNotFoundException: org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
原因: org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping 在 Spring 3.1 就已经标记为废弃(deprecated),到 Spring 5 就删除了。Spring 5 统一使用 RequestMappingHandlerMapping 来处理 @RequestMapping 注解的 Controller。
解决方法 删除RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter 确保xml里有
<mvc:annotation-driven />
2. Spring 5.3.39 升级后 路径匹配规则 发生了变化
触发条件
例如接口声明 @RequestMapping(value = "/xxxx"), 前端发起的请求是 /xxxx.json ,旧版本可以访问,新版本却404
原因
旧版本(AntPathMatcher):路径匹配比较宽松 新版本(PathPatternParser):默认精确匹配,不会自动忽略 .json 这样的后缀。 如果方法上没有声明 .* 或显式的后缀匹配,Spring 会直接 404。
解决方法
方法1 (不推荐毕竟这属于以前欠下的技术债,最好还是规范请求路径)
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(true);
}
}
3.beforeCommit / beforeCompletion 执行时机的微调
触发条件
-
在 TransactionSynchronization.beforeCommit(boolean readOnly) 或 beforeCompletion() 中做了依赖数据库写入结果的业务逻辑,例如提前更新缓存、调用外部接口、发 MQ 消息等
-
升级到 Spring 5.3.39 后,这段逻辑在某些情况下 不会像之前一样被触发(特别是事务被标记 rollback-only 时)
原因分析
-
在 5.3.39 前,Spring 即使事务标记为 rollback-only(但还没真正回滚)也会执行 beforeCommit
-
在 5.3.39 后,Spring 严格遵循:
** 如果事务已经 rollback-only,则不会调用 beforeCommit。
** beforeCompletion 仍会执行,但在回滚场景里可能提前触发。
-
这是为了避免在即将回滚的事务中提前做对外可见的状态变更(防止“幻读”式的业务错误)。
-
如果确实要在提交前做准备,可以放到 beforeCompletion 并且判断事务状态
解决方法
- 不要在 beforeCommit 中做依赖提交结果的逻辑(如发 MQ、写缓存),应该放到 afterCommit
4. afterCommit / afterCompletion 执行的更严格顺序
触发条件
- 代码在 afterCompletion 里区分提交和回滚的逻辑,比如:
@Override
public void afterCompletion(int status) {
if (status == STATUS_COMMITTED) {
// 写缓存
} else {
// 清理资源
}
}
- 升级后发现,有些时候你预期的“提交”逻辑没被触发,或者执行时间点比以前晚。
原因分析
-
5.3.39 后,Spring 将所有 afterCommit 放在真正的物理事务提交后执行(以前可能是在事务管理器完成提交阶段的早一点时间点就执行)。
-
afterCompletion 总会执行,但状态值来源更严格:
** STATUS_COMMITTED → 真正提交成功
** STATUS_ROLLED_BACK → 真正回滚完成
-
对依赖事务状态判断的代码影响比较大,特别是链路中还有异步任务时。
解决方法
- 如果是提交成功后的业务逻辑(如发消息、刷新缓存),全部迁移到 afterCommit,不要依赖 afterCompletion 判断提交状态。
- 如果是清理资源,可以继续用 afterCompletion,但不要在这里做提交后才安全的操作。
升级带来的实际收益
1. 性能与内存优化
- 启动速度可提升 10%-20%(取决于项目规模)
- 内存占用减少,垃圾回收更稳定
2. 安全加固
- 修复已知的数十个安全漏洞(包括反序列化、XSS 等)
- 默认安全策略提升,减少人为配置失误
3. 生态兼容性
- 无缝衔接 Spring Boot 2.x/3.x
- 直接接入最新的 Spring Data、Spring Security、Spring Cloud 组件
4.未来维护成本降低
- 从 4.3 到 5.3 是一次跨越式升级,后续迁移到 Spring 6 成本低很多
- 避免继续堆积技术债务