mababaka

Back

本文整理自 Spring 官方博客、Spring AI GitHub Releases 及社区报道,信息截至 2026-09-22。

为什么值得关注

很长时间里,"做 AI 应用"几乎等同于"写 Python"。LangChain、LlamaIndex 把生态铺得很开,而 Java 团队手里那些跑了好多年的 Spring Boot 服务、关系型数据库、安全与可观测体系,反而像是被隔在门外。

Spring AI 做的就是把这扇门打开。而过去几个月,这个项目接连完成了两次重要动作:2.0.0 正式 GA,以及随后的第一个维护版本 2.0.1。前者重建了地基,后者补齐了生产环境里那些真正会咬人的细节。

时间线:一年半从 1.0 走到 2.0

  • 2025 年 5 月:Spring AI 1.0 GA,第一次给出稳定的、Spring 风格的 AI 应用开发基线——可移植的 Chat、Embedding、Vector Store、结构化输出、工具调用、Chat Memory 抽象,以及一堆 Boot Starter。
  • 2025 年 11 月:1.1 GA,继续在模型支持和能力上做加法。
  • 2026 年 6 月 12 日:Spring AI 2.0.0 GA。
  • 2026 年 8 月 21 日:Spring AI 2.0.1,2.0 线上的首个维护版本。

值得一提的是官方在 GA 公告里的坦率表述:项目在功能、模型支持、用户和贡献上增长得太快,所以他们主动"退后一步",重新定义了范围、质量和一致性的基线。这不是一次版本号升级,而是一次刻意的重构。

2.0.0 GA:重新浇筑的地基

平台基线整体上移

2.0 面向 Spring Boot 4.0 / 4.1 与 Spring Framework 7.0 设计。随之而来的几项改动,对长期维护的项目意义很大:

  • Jackson 3:JSON 序列化链路上的改进,并新增 JsonHelper 用于提供完全自定义的 JsonMapper。
  • JSpecify 空安全注解:整个代码库完成标注,既能提前拦截运行期的 NPE,也让 Kotlin API 更符合语言习惯。
  • Options 体系重构:明确哪些选项必填、哪些可选;默认值统一收敛到 options 层;options 改为 builder 创建且创建后不可变;builder 提供一致的、免反射的合并能力。顺带还去掉了配置属性里那个多余的 .options 层级,修掉了一批相关 bug。

还有一个使用层面的导向被明确下来:ChatClient 是面向用户的常用 API,ChatModel 则退居为更底层的构件。

模型支持从"铺开"转为"收敛"

这是 2.0 里最容易被低估的决策。核心仓库现在聚焦一组明确的开箱即用聊天模型:OpenAI、Anthropic、Amazon Bedrock、Google GenAI、Mistral AI、DeepSeek、Ollama。

同时做减法:

  • OpenAI 从 3 种实现(Azure / HTTP / SDK)收敛为 1 种(SDK)
  • Anthropic 从 2 种(HTTP / SDK)收敛为 1 种(SDK)
  • Google GenAI 从 2 种(GenAI SDK / Vertex)收敛为 1 种(GenAI SDK)

转向厂商官方 SDK 的收益是长期的——模型 API 一有新扩展,框架能更快跟上。而那些不适合进核心的集成,官方选择了另一条路:交给厂商自己维护。Oracle 的 OCI Generative AI、微软的 Azure Cosmos DB 都已成为由厂商协作维护的外部模块——Cosmos DB 那边一次性给出了向量存储、对应自动配置、ChatMemoryRepository 实现和它的自动配置共四个模块。

Agent 能力:把工具调用从"私有循环"里解放出来

这是 2.0 在架构上最实质的变化。

在 1.x 里,每个 ChatModel 内部都藏着一套自己的工具调用循环,埋在实现深处,既没法挂钩、没法包装,也没法替换执行策略。用官方那句很精准的话说:"你可以调用工具,但你无法在工具调用之上构建东西。"

2.0 把这个循环提升为 advisor 链上的一等可组合组件。ChatClient 让每个请求都流经一条有序的 advisor 链,并支持循环——advisor 可以重新进入下游链路。同一套机制同时驱动了工具调用循环、结构化输出重试循环和评估循环。

几个具体落点:

  • ToolCallingAdvisor:由 ChatClient 自动注册,实现完整的工具调用往返。各 ChatModel 里那些临时性的工具循环被彻底移除。需要精确控制每一次迭代时,也可以选择退出、手动驱动循环。
  • ToolSearchToolCallingAdvisor:面向"工具有几百个"的场景。不再把全部工具定义塞进每个请求,而是在会话内一次性索引全量工具集,让模型按需检索相关工具——渐进式工具披露。在大规模 MCP 配置下,工具定义本身可能就要吃掉每次请求 10–21K tokens;官方在 OpenAI、Anthropic、Gemini 上的基准测试显示,这一机制把 token 消耗降低了 34%–64%,且没有可测量的准确率损失。它可以用配置直接开启。
  • StructuredOutputValidationAdvisor:即使开了原生结构化输出,模型依然可能吐出不合规的 JSON。这个可自动注册的 advisor 会在校验失败后自我纠正。
  • AugmentedToolCallbackProvider:包装工具对象、在执行前拦截模型给出的工具参数。配合 AgentThinking 参数类型,每次工具调用都会带上模型填写的 innerThought 字段——相当于结构化的思维链,应用可以直接记录、展示或据此路由,而不必事后解析。

一个容易被忽略的细节:MessageChatMemoryAdvisor 放在 ToolCallingAdvisor 之前还是之后,决定了完整工具调用记录是否被持久化。想要精简的对话历史,就把 memory 放在工具调用之前;想留审计轨迹,就放在之后。

社区扩展补上两块拼图

  • spring-ai-session:内置 ChatMemory 的事件溯源替代方案,支持包括工具调用在内的全部消息类型(在任何后端下都能安全地处于工具调用循环内),并在上下文窗口填满时应用可插拔的、按轮次感知的压缩策略——包括由 LLM 驱动的摘要。
  • spring-ai-agent-utils:在 2.0 的 agent 地基之上,提供打包成可组合工具与 advisor 的生产级原语,包含 Agent Skills(AgentSkills 规范的可移植 Spring AI 原生实现),以及 file、shell、web-fetch、task、auto-memory 等实用工具。

MCP 从"集成"变成"主线剧情"

Model Context Protocol 正在成为 AI 集成的通用协议。Spring 团队本身就在维护官方 MCP Java SDK,所以 Spring AI 的 MCP 集成能贴着规范源头走。2.0 带来的变化包括:

  • 随版本发布 MCP Java SDK 2.0.0,符合最新的 2025-11-25 版 MCP 规范,并把整个 MCP 生态收拢到 Spring AI 名下。
  • 注解驱动编程模型:原先在社区孵化的 mcp-annotations 模块正式进入 Spring AI。@McpTool、@McpResource、@McpPrompt 让任意 Spring 服务只需一个方法注解就能暴露为 MCP 服务端能力。统一的 McpSyncRequestContext / McpAsyncRequestContext 会被自动注入服务端处理方法,为工具和资源提供日志、进度上报、sampling、elicitation 的单一入口。客户端侧同样是一等公民,声明式 handler 覆盖了完整的协议回调模型。
  • 传输层:WebMVC 与 WebFlux 传输实现从 MCP Java SDK 移入 Spring AI,发布节奏与框架对齐。Streamable HTTP 成为默认传输,取代已废弃的 SSE(其无状态变体可用于换取远程部署的可伸缩性,代价是放弃 MCP 的双向通信);STDIO 仍可用于本地进程集成。
  • 企业特性:直接继承 Spring 的生产栈——面向服务端交互的 Micrometer span 与 OpenTelemetry 兼容指标,以及经由社区项目 mcp-security 提供的 OAuth 2.0 与 API Key 安全。

此外还有一处治理上的调整值得一提:随着编码 agent 提交的 PR 已占绝大多数,官方重写了 CONTRIBUTING.md,同时面向人类与 agent 明确贡献规则与约定,并强调人工评审的必要性。

2.0.1:一个"维护版本"该有的样子

2.0.1 处理了 80 多个 issue 和 PR,并且修复了 7 个 CVE。只看版本号容易低估它。

安全:7 个 CVE,其中几个值得特别留意

CVE 问题
CVE-2026-47851 PDF Document Reader 中对攻击者可控的 PDF 大纲树进行无界递归
CVE-2026-47852 可预测的缓存目录位置,允许本地 ONNX 模型替换
CVE-2026-59279 通过重复 initialize 请求造成无界持久会话分配
CVE-2026-59294 ResourceCacheService 中的路径穿越导致任意文件写入
CVE-2026-59308 语义缓存因 SHA-256 截断导致的跨租户隔离绕过
CVE-2026-59319 RedisChatMemoryRepository 中的 RediSearch Tag 注入,导致跨会话数据泄露
CVE-2026-59318 DefaultToolCallingManager 全局解析器兜底允许通过提示注入派发未声明的工具

如果只看一条,那就是 CVE-2026-59318——提示注入竟能派发未被声明的工具,这正是 agent 类应用最典型的攻击面。而 CVE-2026-59308 和 CVE-2026-59319 则提醒我们:AI 应用的多租户隔离是全新的课题,语义缓存和会话内存都可能成为越权读取的通道。

结论很简单:跑在 2.0.0 上的应用应当尽快升到 2.0.1。

新能力

  • 工具调用次数上限:agentic loop 停不下来是最昂贵的失败模式。ToolCallingAdvisor 现在支持配置单次请求的最大工具调用次数,达到上限抛出 ToolCallLimitExceededException;异常路径会返回单个 Generation,让错误处理与正常响应保持同一形状。相关的工具解析兜底策略也可配置——无法解析的工具名,是快速失败还是回退,由你决定。
  • OpenAI 音频:OpenAiAudioSpeechModel 支持音频流式输出,并暴露 instructions 选项以引导音色与表达方式;转写侧的选项与响应也被扩充,覆盖了更多 OpenAI API 面。
  • Google GenAI:新增 ToolChoice 支持(强制调用、禁用调用,或交给模型判断),并接入统一 ImageModel 抽象的图片生成能力。
  • 文档读取:PagePdfDocumentReader 支持页码范围——几百页的文档终于可以只读取需要的部分;TokenTextSplitter 开始校验 builder 参数,而不是在后续抛出令人费解的错误。
  • AWS 区域解析:Spring AI 现在遵循 AWS SDK 的默认区域解析规则,也不再在解析区域时打印令人困惑的 WARN。如果你的 Bedrock 依赖环境变量或 profile 配置区域,行为终于和 AWS 栈的其余部分一致了。

可靠性修复的重点

流式响应承担了这次最多的注意力:OpenAiChatModel 按索引合并流式工具调用的增量、正确处理空的 tool_calls 数据块、修掉了流式模式下 token 用量为零的报告;取消流后不再泄漏底层 HTTP 响应(chat 与音频转写都修了);ToolCallingAdvisor 的流式循环不再丢弃 doBeforeStream 的修改;token 用量改为跨工具调用迭代累计,而不再只报最后一轮。

Chat Memory 方面,Redis ChatMemoryRepository 三处加固:时间戳原子预留(并发写入不再撞车)、clear() 真正生效、查询中的元数据值被正确转义。

向量库方面,Milvus 修了三处(过滤表达式的分组优先级、整型元数据被反序列化成 Long 而非 Double、针对自定义元数据字段的过滤),OpenSearch 修复文档反序列化,PgVector 在初始化后校验表结构而不是等到第一次查询才失败,Couchbase 的 builder 断言也修正了。

MCP 方面,注解在 GraalVM native image 下恢复可用,@McpTool 的异常处理与 @Tool 契约对齐,无参数的 stdio 连接可用,HTTP 客户端请求定制器 bean 被正确应用,Streamable HTTP WebClient 传输可以接受省略 event 字段的 SSE 帧;服务端还能用 maxSessions 与 sessionIdleTimeout 限制会话状态。

健壮性方面,一批修复让框架面对不可信输入时更稳重:校验已解析的资源路径、缓存改用临时目录、用完整长度哈希替换截断哈希、处理畸形 PDF 而不是直接把解析器异常抛出去。另外,协议值的大小写转换改用 Locale.ROOT,顺手修掉了那个经典的土耳其语 i 问题。

升级前请注意

从 2.0.0 到 2.0.1 多数应用改个版本号即可,但有几处需要留意:

  • 已废弃的 Mistral AI 聊天模型被正式退役,仍按常量引用的需要换成受支持的模型名。
  • Redis chat memory 自动配置模块改名,与 spring-ai-autoconfigure-* 命名保持一致,构建文件里的 artifact id 要更新。
  • OpenAI 工具调用 strict 模式默认值改为 false。生成的工具 schema 通过把可选参数从 required 中省略来表达"可选",而 strict 模式不接受这一点——于是任何带可选参数的工具都会以 400 报错。现在 strict 模式改为显式启用,与 OpenAI API 的默认行为一致。
  • Media builder 改用带类型的 data 重载,接受的数据类型变得明确,不再笼统地接收 Object。
  • DeepSeekApi 被修订,以与其他 API 客户端的约定保持一致。
  • Couchbase 向量存储改用 Spring Boot 管理的 Couchbase 客户端,从而参与应用已经声明的集群配置。

如果你还在 1.x:这不是一次"打个补丁"

从 1.1.x 升到 2.0.0 的破坏性变更需要预留时间,升级说明里写得很清楚:

  • 应用配置键里的 .options 层级被移除;
  • toolNames() 与 SpringBeanToolCallbackResolver 被删除,工具必须注册为 ToolCallback bean 并通过 .tools() 显式传入;
  • 各 ChatModel 内部的工具调用循环不复存在;
  • 模块被重命名、类被移动,advisor 与工具搜索相关的改动尤其集中。

回报是一套连贯可预期的 API 表面,以及一个真正能"在工具调用之上构建东西"的框架。

小结

把这两次发布放在一起看,方向相当清楚:

2.0.0 解决的是"地基"问题——统一基线、统一选项语义、把工具调用提升为可组合的一等组件、把 MCP 纳入主线、收敛模型支持并用厂商 SDK 换取长期跟进能力。

2.0.1 解决的是"上生产"问题——给 agentic loop 装上明确的调用边界,修掉 7 个 CVE,补齐流式、内存、向量库、MCP 里那些只在真实负载下才暴露的缺陷。

对 Java 团队来说,意义或许比版本号更大:生成式 AI 正在从"另一个用别的语言写的边车"变成"应用栈里再普通不过的一组能力"。你依然用 starter、自动配置、依赖注入、模板、advisor、注解、repository 和可观测性来做这件事——只是现在,模型、向量库、工具和 MCP 也在这套体系里了。

参考链接

Spring AI 近期动态全梳理:从 2.0 GA 到 2.0.1,Java 的 AI 应用栈走向成熟
https://haustlyb.cn//archives/spring-ai-2-0-ga-and-2-0-1-roundup
Author Administrator
Published at 九月 22, 2026