Spring AI 2.0 升级实录:7 个真实踩坑与完整迁移检查清单
摘要:本文记录一次真实的 Spring AI 1.0.9 → 2.0.0 生产级升级(WMS 智能仓储项目,Spring Boot 3.5 → 4.1.0),每个坑都附带真实报错信息与复现路径,结尾给出 8 项升级检查清单,可直接对照执行。
文章目录
- [Spring AI 2.0 升级实录:7 个真实踩坑与完整迁移检查清单](#Spring AI 2.0 升级实录:7 个真实踩坑与完整迁移检查清单)
-
- 一、升级环境对照
- [二、7 个真实踩坑记录](#二、7 个真实踩坑记录)
-
- [坑 1:Spring Boot 4 是硬门槛,没有商量余地](#坑 1:Spring Boot 4 是硬门槛,没有商量余地)
- [坑 2:所有 Options 的 setter 方法全部移除](#坑 2:所有 Options 的 setter 方法全部移除)
- [坑 3:ChatModel 的工具调用循环被抽走(最隐蔽)](#坑 3:ChatModel 的工具调用循环被抽走(最隐蔽))
- [坑 4:PromptChatMemoryAdvisor 移除,会话记忆必须显式给 ID](#坑 4:PromptChatMemoryAdvisor 移除,会话记忆必须显式给 ID)
- [坑 5:传递依赖悄悄消失,编译期才暴露](#坑 5:传递依赖悄悄消失,编译期才暴露)
- [坑 6:Jackson 3,最容易被低估的破坏性变更](#坑 6:Jackson 3,最容易被低估的破坏性变更)
- [坑 7:Boot 4 的运行期杂症(实测两例)](#坑 7:Boot 4 的运行期杂症(实测两例))
- 三、升级检查清单
- 四、总结
一、升级环境对照
| 项 | 升级前 | 升级后 |
|---|---|---|
| Spring AI | 1.0.9 | 2.0.0 |
| Spring Boot | 3.5.x | 4.1.0 |
| JDK | 17 | 21 |
| Jackson | 2.x | 3.x |
| 向量库 | PgVector | SimpleVectorStore |
| 数据库 | PostgreSQL | MySQL 8 |
核心结论一句话:Spring AI 2.0 = Boot 4 + Framework 7 + Java 17 最低(推荐 21)+ Jackson 3 的全家桶硬绑定,不是独立升级某个依赖就能搞定的事。
二、7 个真实踩坑记录
坑 1:Spring Boot 4 是硬门槛,没有商量余地
Spring AI 2.0 的依赖树直接压在 Boot 4 / Framework 7 上,Boot 3.x 环境下根本加载不起来。这不是"建议升级",而是"不升就用不了"。
时间线上也要注意:Spring Boot 3.5 和 Framework 6.2 已于 2026 年 6 月 30 日停止维护,留在 1.x 的团队安全更新通道正在关闭。
推荐升级路径:先升 Boot 3.5 清完全部废弃警告,再一步跳 4.x。跳步的代价是编译期被移除的 API 一堆糊脸上。
坑 2:所有 Options 的 setter 方法全部移除
升级后第一波编译报错来源:
java
// 1.x 能编译通过
options.setTemperature(0.7);
options.setModel("qwen2.5:7b");
// 2.0 直接编译失败,setter 不存在
2.0 的 Options 对象全面转向 Builder 模式 + 不可变设计 ,setTemperature、setModel、setMaxTokens 一个都找不到。
迁移方法:全局搜索 .setTemperature|.setModel|.setMaxTokens,机械替换为 XxxOptions.builder().xxx().build() 链式调用。
坑 3:ChatModel 的工具调用循环被抽走(最隐蔽)
这是本次升级最隐蔽的破坏性变更。
1.x 中 chatModel.call(prompt) 会自动执行工具调用并循环到产出最终答案。2.0 把这个循环从 ChatModel 内部提升为 Advisor 链中的一等公民(ToolCallingAdvisor)。
直接后果:直接调用 ChatModel 且挂载了工具的代码,现在只返回第一次 tool-call 响应就结束,框架不再帮你执行工具。
两种解法:
java
// 方案一(推荐):走 ChatClient,ToolCallingAdvisor 自动注册,行为无感
chatClient.prompt()
.tools(myTools)
.call();
// 方案二:坚持裸用 ChatModel,需自行通过 ToolCallingManager 驱动工具循环
附带收益:工具循环可插拔了,可以自定义执行策略、拦截器、重试逻辑------这在 1.x 中无法实现。
坑 4:PromptChatMemoryAdvisor 移除,会话记忆必须显式给 ID
1.x 的隐式会话状态管理不复存在,2.0 的 ChatMemory Advisor 强制要求显式 conversationId。
多用户 × 多仓库场景下,会话需要按「用户 ID + 仓库编码」隔离,官方只提供内存和 JDBC 实现,均不满足需求,最终自研了 Redis 版 ChatMemoryRepository:
conversationId = userId + ":" + warehouseCode组合键;- Redis List 存储(天然保序)+
LTRIM裁剪最近 20 轮 +EXPIRE设置过期; - 实现
ChatMemoryRepository接口后挂载MessageWindowChatMemory,语义与官方完全对齐。
另外注意:ChatMemory 相关接口在 2.0 中位于 spring-ai-model 包,不要再去 core 包里找。
坑 5:传递依赖悄悄消失,编译期才暴露
原项目用 pgvector starter 做向量库,迁移 MySQL 时更换轻量方案、摘除 pgvector 依赖后,整个 RAG 链路编译失败:
text
程序包 org.springframework.ai.vectorstore 不存在
实测结论:spring-ai-vector-store 并不是 ollama starter 的传递依赖 (此前是由 pgvector starter 带入的)。升级或替换 starter 后,凡是用到 VectorStore 接口的模块,必须显式补上依赖。
替代方案:SimpleVectorStore(2.0 的 spring-ai-vector-store 包内置),内存检索 + JSON 文件定时落盘,启动自动恢复,零外部依赖,私有化部署场景下反而更合适。
坑 6:Jackson 3,最容易被低估的破坏性变更
包名从 com.fasterxml.jackson 换成 tools.jackson,这个编译期就能发现,不算大问题。
真正隐蔽的是序列化默认值变化:日期格式、字段顺序都与 Jackson 2 不同。接口 JSON 输出可能悄悄变脸,依赖固定格式的下游解析方会直接出错。
这不是 Spring AI 的坑,而是 Boot 4 带来的。建议:升级前后各跑一轮集成测试,显式 diff JSON 输出。
坑 7:Boot 4 的运行期杂症(实测两例)
① Tomcat 相关类挪包:org.springframework.boot.tomcat.TomcatWebServer,凡是反射访问 Boot 内部类的代码需要同步修改。
② spring-boot:run 启动时,yml 中配置的 server.port 失效,Tomcat 起在随机端口上,配置文件、环境变量、代码三处均查不到覆盖源。目前用命令行参数强制指定绕过:
bash
mvn spring-boot:run -Dspring-boot.run.arguments=--server.port=8089
如有人遇到同样的问题,欢迎在评论区交流,怀疑与 Boot 4.1 的 yml 解析行为变化有关。
三、升级检查清单
- 先升 Boot 3.5,清完废弃警告,再跳 Boot 4;
- JDK 换 21(最低 17);
- 全局替换 Options 的 setter → Builder 链式调用;
- 排查所有直接调用 ChatModel 的工具调用代码,迁移到 ChatClient 或自行驱动循环;
- ChatMemory 全量审计:显式 conversationId + 选定 Repository 实现;
- VectorStore 依赖显式化,不要依赖传递依赖;
- Jackson 3 序列化 diff 测试;
- 通过反射/字节码增强访问过 Boot 内部类的代码,跟随挪包修改。
四、总结
这轮升级的本质:Spring 把 AI 能力从"框架帮你兜底"改成了"显式声明、显式组装"。短期是迁移阵痛,长期看------工具调用可插拔、Options 不可变、会话状态强制显式化,全是在为 Agentic 应用铺路。
痛归痛,方向是对的。