Spring AI 技术架构与源码分析
一句话概括:Spring AI 不是又一套 AI SDK 封装,而是一套以"Spring 风格的标准接口"为设计哲学、以"Advisor 责任链"为编排管线、将"工具调用循环"从模型内部私有逻辑升级为可组合、可观测、可递归的一等公民的 Java AI 开发框架------让 Spring 开发者像操作普通 Service 一样操作大模型,像写 Spring AOP 一样编排 AI 工作流。
一、引言
如果你是一个 Spring 开发者,想在项目里接入大模型,你可能会写下类似这样的代码:
java
@RestController
public class ChatController {
@GetMapping("/chat")
public String chat(@RequestParam String message) {
RestTemplate restTemplate = new RestTemplate();
String url = "https://api.openai.com/v1/chat/completions";
// 构造请求头、请求体、处理 JSON...
// 几十行样板代码
return response;
}
}
几十行代码,手动构造 HTTP 请求、解析 JSON、处理异常。看起来很繁琐,对吧?
但当你的应用需要从 OpenAI 切换到通义千问,业务方说"明天换一家"时;当你的多轮对话需要记忆上下文,但又不能把所有历史都塞给模型时;当你需要给某一部分请求加脱敏、另一部分加审计,且这些横切逻辑不能散落在 Controller 里时------这段手写的 HTTP 调用代码还够用吗?
显然不够。
Spring AI 正是为回答这个问题而生的。
Spring AI 是 Spring 官方推出的 AI 应用开发框架,其核心目标是将 Spring 生态系统的设计原则------高度的可移植性、依赖注入、模块化设计以及基于 POJO 的应用构建方式------引入 AI 领域 。2026 年 6 月 12 日,Spring AI 2.0.0 GA 正式发布,这是 Spring AI 项目自 1.0.0 GA 以来最大的一次版本升级。截至 2026 年 8 月,项目已拥有超过 50 位社区贡献者,支持 15+ 家 AI 模型提供商。
那么,这个"AI 界的 Spring Data"到底是如何设计的?为什么 2.0 把工具调用从模型内部的私有逻辑变成了 Advisor 链上的一等公民?Advisor 的洋葱模型背后是什么原理?我们从源码出发,一步步拆解。
二、整体架构与设计哲学
2.1 架构总览:分层解耦 + 模块化设计
Spring AI 采用分层架构设计,延续了 Spring 一贯的"抽象与解耦"设计哲学:
┌──────────────────────────────────────────────────────────────────────┐
│ 应用层(Application) │
│ ChatClient(统一客户端)· Agentic Workflows · Skills │
├──────────────────────────────────────────────────────────────────────┤
│ Advisor 管线层 │
│ 五阶段责任链:日志 · 记忆 · RAG · 工具调用 · 结构化输出 │
│ ToolCallingAdvisor(递归)· MessageChatMemoryAdvisor · ... │
├──────────────────────────────────────────────────────────────────────┤
│ 核心抽象层(Core Layer) │
│ Model · ChatModel · EmbeddingModel · Prompt · Response │
│ 以"抽象即自由"为理念,屏蔽 15+ 模型提供商差异 │
├──────────────────────────────────────────────────────────────────────┤
│ 集成层(Integration Layer) │
│ spring-ai-openai · spring-ai-anthropic · spring-ai-ollama │
│ spring-ai-mcp · spring-ai-vector-store · ... │
└──────────────────────────────────────────────────────────────────────┘
图:Spring AI 的四层架构。最底层是集成层,对接具体模型提供商;核心抽象层定义统一接口;Advisor 管线层是 2.0 的核心创新------将工具调用循环从模型内部提升为可组合的责任链;应用层提供 ChatClient 和 Agentic Workflows 等高层 API。
各层职责:
| 层级 | 职责 | 关键模块 |
|---|---|---|
| 应用层 | 面向开发者的高层 API,开箱即用 | ChatClient、Agentic Workflows、Skills |
| Advisor 管线层 | 2.0 核心创新:责任链编排,递归 Advisor 实现工具调用循环 | ToolCallingAdvisor、MessageChatMemoryAdvisor |
| 核心抽象层 | 定义与模型无关的接口,是 Spring AI 的"灵魂" | Model、ChatModel、Prompt、Response |
| 集成层 | 对接具体 AI 模型提供商 | spring-ai-openai、spring-ai-anthropic、spring-ai-ollama |
看到这里,你可能会问:为什么 Spring AI 要把 Advisor 管线单独列为一层?
因为这是 2.0 版本最大的架构变化。在 1.x 中,工具调用循环被埋在每一个 ChatModel 实现内部------能用,但无法钩入、无法观察中间步骤、无法与其他行为组合。2.0 把工具调用循环提升到 Advisor 链中作为一等公民。理解了 Advisor 链,就理解了 Spring AI 2.0 的一半。
2.2 设计哲学:抽象即自由,管线即编排
Spring AI 的设计围绕几个核心哲学展开:
哲学一:抽象即自由。 正如 JdbcTemplate 统一了数据库访问,Spring AI 在 AI 领域建立了一套通用编程模型。通过统一接口屏蔽底层模型差异,实现"一次编码,多模型运行"。
哲学二:管线即编排。 2.0 将原本隐藏在模型内部的循环能力升级为递归 Advisor(如工具调用循环、结构化输出校验重问),使跨关注点的治理与观测能够统一装配在同一条链上。
哲学三:渐进式抽象。 开发者可以从底层的 ChatModel 开始,逐步过渡到高层的 ChatClient 和 Advisor 链,按需选择抽象层级。
哲学四:POJO 为中心。 使用普通 Java 对象作为应用构建块------Prompt、Message、ChatResponse 都是 POJO。
官方设计原则:
| 原则 | 含义 | 在框架中的体现 |
|---|---|---|
| 可移植性 | 在不同 AI 模型提供商之间切换时,代码改动最小 | 统一的 Model 接口,切换提供商只需更换依赖和配置 |
| 模块化设计 | 将 AI 开发拆分为独立模块,支持按需组合 | spring-ai-core 定义契约,各集成模块独立实现 |
| 约定优于配置 | 减少显式配置,自动推断默认行为 | Spring Boot 自动配置,引入即用 |
| 依赖注入 | 组件通过 Spring 容器管理 | ChatClient、Advisor 等均可注入使用 |
2.3 包结构与代码规模
Spring AI 采用标准的 Maven 多模块结构。2.0 版本从 1.x 的单体核心重构为专业化领域模块:
spring-ai/
├── spring-ai-core/ # 核心抽象(Model, ChatModel, Prompt, Advisor API)
├── spring-ai-client-chat/ # ChatClient 实现 + Advisor 实现
├── spring-ai-openai/ # OpenAI 集成
├── spring-ai-anthropic/ # Anthropic Claude 集成
├── spring-ai-ollama/ # Ollama 本地模型集成
├── spring-ai-mcp/ # Model Context Protocol 集成
├── spring-ai-vector-store/ # 向量存储抽象
├── spring-ai-spring-boot-starter/# Spring Boot 自动配置
└── spring-ai-bom/ # 依赖管理 BOM
Spring AI 2.0 构建在 Spring Boot 4.0/4.1 和 Spring Framework 7.0 之上。整个代码库采用 JSpecify 注解 实现空安全,Jackson 3 序列化全面升级。
2.4 技术栈速览
| 层次 | 技术选型 |
|---|---|
| 语言 | Java 17+ |
| 构建工具 | Maven |
| 核心依赖 | Spring Framework 7.0、Spring Boot 4.0/4.1 |
| 响应式支持 | Project Reactor(Flux/Mono) |
| 序列化 | Jackson 3(2.0 版本升级) |
| 可观测性 | Micrometer / OpenTelemetry |
| 许可证 | Apache 2.0 |
三、核心抽象与编程模型
3.1 Model 与 ChatClient------从底层到高层的分工
好了,现在来回答刚才那个问题:Spring AI 是如何用一套 API 屏蔽十几家 AI 服务商差异的?
答案就是 Model 接口和 ChatClient 的分层设计。
在 Spring AI 2.0 中,ChatClient 已成为最常用的用户 API,而 ChatModel 降级为底层构建块。
java
// 文件路径:spring-ai-core(结构示意)
// 底层:ChatModel ------ 直接封装与 AI 模型的通信
ChatModel chatModel = new OpenAiChatModel(apiKey);
ChatResponse response = chatModel.call(new Prompt("你好"));
// 高层:ChatClient ------ 门面模式,封装了 ChatModel 的底层细节
ChatClient chatClient = ChatClient.create(chatModel);
String response = chatClient.prompt("你好")
.system("你是一个博学的智能聊天助手")
.call()
.content();
看到了吗? ChatClient 帮你省去了构造 Prompt、解析 ChatResponse 的步骤。它还支持链式配置------.prompt().system().tools().call()------这是建造者模式(Builder Pattern) 的典型应用。
Model 接口的设计 :Model 是所有 AI 模型的根接口,只包含一个 call 方法。这种极简设计使得所有 AI 模型都具有统一的调用方式 ,是策略模式(Strategy Pattern) 的体现。
设计权衡分析:
-
收益 :①统一的模型接口让开发者可以在 15+ AI 提供商之间自由切换;②
ChatClient门面将样板代码降至最低;③与 Spring 生态无缝集成,支持依赖注入。 -
代价 :①泛型抽象增加了框架的复杂度,新手可能需要花时间理解类型参数;②所有模型必须适配统一的接口契约,对于某些模型特有的高级特性(如 OpenAI 的 JSON mode),需要通过
ModelOptions传递。 -
适用场景:在需要集成多个模型提供商的企业级 Spring Boot 项目中,统一抽象带来的可移植性收益远大于学习成本。
3.2 Advisor------从 AOP 到 AI 管线的进化
Advisor 在 Spring AI 中直译为"顾问",本质上和 Spring AOP 切面 是同类东西,内部采用责任链模式实现。
java
// 文件路径:spring-ai-client-chat(结构示意)
// 最简单的内置日志 Advisor
org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor
Advisor 的主要职责是对 Chat 交互过程进行前后增强 。你可以通过 Advisor 实现:
- 日志记录(
SimpleLoggerAdvisor) - 对话记忆(
MessageChatMemoryAdvisor) - 检索增强 RAG(
RetrievalAugmentationAdvisor) - 工具调用循环(
ToolCallingAdvisor------2.0 版本的核心变化) - 结构化输出自纠错(
StructuredOutputValidationAdvisor)
设计模式解读 :Advisor 体系是责任链模式(Chain of Responsibility Pattern) 和装饰器模式(Decorator Pattern) 的结合。ChatClient 在每次请求时按 order 排序执行一链 Advisor,请求按 order 从小到大依次经过每个 Advisor,抵达链尾的 ChatModel 完成真正的调用;响应反向穿回。
3.3 洋葱模型------Advisor 链的执行机制
Spring AI 2.0 的 Advisor 管线采用洋葱模型执行:
┌─────────────────────────────────┐
│ SimpleLoggerAdvisor(外层) │
│ ┌─────────────────────────────┐│
│ │ MessageChatMemoryAdvisor ││
│ │ ┌─────────────────────────┐││
│ │ │ ToolCallingAdvisor │││
│ │ │ ┌─────────────────────┐│││
│ │ │ │ ChatModel 调用 ││││
│ │ │ └─────────────────────┘│││
│ │ └─────────────────────────┘││
│ └─────────────────────────────┘│
└─────────────────────────────────┘
图:Spring AI Advisor 的洋葱模型。请求从外到内穿透 Advisor 链,响应从内到外返回。每个 Advisor 都可以在请求前后插入逻辑。
一次 chatClient.prompt().user(...).call() 不会直接打到模型 API,而是穿过一条按 order 排序的 Advisor 链:
- 请求按
order从小到大依次经过每个 Advisor(数值越小越靠外层) - 抵达链尾的
ChatModel完成真正的调用 - 响应反向穿回,每个 Advisor 可以在响应返回前做后置处理
每个 Advisor 都提供 before 和 after 方法。这种设计让开发者可以在不修改核心逻辑的情况下,在请求前/后插入任意增强逻辑。
3.4 ToolCallingAdvisor------2.0 最大的架构变化
这是 Spring AI 2.0 最大的架构变化。
在 1.x 中,每个 ChatModel 实现都包含自己的私有工具执行循环------能用,但没法钩入、没法观察中间步骤、没法与其他行为组合。
Spring AI 2.0 将工具循环提升为 Advisor 链中的一等公民 ------ToolCallingAdvisor。
java
// 文件路径:spring-ai-client-chat(结构示意)
// ToolCallingAdvisor 是一个递归 Advisor
// 它会重复进入下游链,直到满足停止条件
// 停止条件:模型产生不含工具调用的响应
ToolCallingAdvisor 的工作原理:
@Tool注解定义工具------框架自动生成输入参数的 JSON Schema- Advisor 提取工具的名称、描述和输入 schema,注入到初始上下文中
- 每轮迭代:累积的对话历史与当前上下文合并,发送给 LLM
- 检查响应:
- 包含工具调用 →
ToolCallingManager查找并执行工具 → 追加结果 → 循环 - 无工具调用 → 返回最终答案给用户
- 包含工具调用 →
- 阻塞(
.call())和流式(.stream())模式完全支持
设计模式解读 :ToolCallingAdvisor 是递归装饰器模式(Recursive Decorator Pattern) 的创新应用------它不仅"装饰"请求/响应,还能在检测到工具调用时重新进入整个处理链。这种设计将工具循环从"埋在模型实现里的私有逻辑"变成了"可组合、可观察、可扩展的一等公民"。
设计权衡分析:
-
收益:①工具循环不再是黑盒,开发者可以通过 Advisor 链观察、组合、扩展工具调用行为;②同一个递归机制同时驱动工具调用循环、结构化输出重试循环和评估循环;③阻塞和流式模式完全支持。
-
代价 :①递归 Advisor 的实现复杂度显著高于 1.x 的私有循环;②Advisor 链的执行顺序变得至关重要------
ToolCallingAdvisor的默认顺序是HIGHEST_PRECEDENCE + 300,前后 Advisor 的位置决定了它们看到的是最终结果还是每次迭代。 -
适用场景:需要精细控制工具调用行为、观察中间步骤、组合多个增强逻辑的生产级 Agent 系统。
3.5 @Tool------让 Java 方法成为 AI 的"双手"
工具调用(Tool Calling)是 Agentic AI 系统的基础构建块 。Spring AI 2.0 中最简单的工具定义方式是通过 @Tool 注解:
java
class WeatherTools {
@Tool(description = "Get the current weather for a given city")
public String getWeather(String city) {
return weatherService.fetch(city);
}
@Tool(description = "Book a flight between two cities on a given date")
public BookingConfirmation bookFlight(
String origin,
String destination,
@ToolParam(description = "Date in YYYY-MM-DD format") String date) {
return flightService.book(origin, destination, date);
}
}
Spring AI 自动生成输入参数的 JSON Schema 。@ToolParam 为每个参数添加描述和可选/必填提示。用 @Nullable 注解的参数默认被视为可选。
工具通过 .tools() 方法显式传递给 ChatClient:
java
String response = ChatClient.create(chatModel)
.prompt("阿姆斯特丹天气怎么样?如果晴天就订一张从伦敦出发的机票。")
.tools(new WeatherTools())
.call()
.content();
看到了吗? 你只需要在 Java 方法上加一个 @Tool 注解,框架就自动完成了从方法签名到 JSON Schema 的转换------反射 + 注解,这是 Spring 开发者最熟悉的模式。
四、核心模块源码解析
4.1 核心抽象层------spring-ai-core
职责:定义所有核心接口和数据类型,是整个框架的"契约层"。
java
// 文件路径:spring-ai-core(结构示意)
public interface Model<TReq extends ModelRequest<?>, TRes extends ModelResponse<?>> {
TRes call(TReq request);
}
public interface ModelClient<TReq extends ModelRequest<?>, TRes extends ModelResponse<?>> {
TRes call(TReq request);
}
Model 和 ModelClient 接口使用 Java 泛型来适应不同类型的请求和响应,增强了不同 AI 模型实现之间的灵活性和适应性。
设计模式解读 :Model 接口是策略模式(Strategy Pattern) 的体现------它定义了统一的执行契约,所有具体模型提供商各自实现自己的调用策略。
4.2 ChatClient------门面模式的精妙实践
职责:提供统一的聊天客户端,是 Spring AI 面向开发者的核心 API。
java
// 文件路径:spring-ai-client-chat(结构示意)
public class ChatClient {
private final ChatModel chatModel;
private final List<Advisor> advisors; // 责任链
// 静态工厂方法
public static ChatClient create(ChatModel chatModel) {
return builder(chatModel).build();
}
// Builder 入口
public static Builder builder(ChatModel chatModel) {
return new DefaultChatClientBuilder(chatModel);
}
// 创建 Prompt 请求
public PromptRequestSpec prompt(String userMessage) {
return new DefaultPromptRequestSpec(this, userMessage);
}
// 核心调用方法
public ChatResponse call(Prompt prompt) {
// 1. 执行 Advisor 链(前置增强)
for (Advisor advisor : advisors) {
prompt = advisor.before(prompt);
}
// 2. 调用底层 ChatModel
ChatResponse response = chatModel.call(prompt);
// 3. 执行 Advisor 链(后置增强)
for (Advisor advisor : advisors) {
response = advisor.after(response);
}
return response;
}
}
设计模式解读 :ChatClient 是门面模式(Facade Pattern) 和建造者模式(Builder Pattern) 的结合------它封装了 ChatModel 的复杂交互,同时通过 DefaultChatClientBuilder 提供了流畅的 API 构建体验。Advisor 链的执行体现了责任链模式(Chain of Responsibility Pattern)。
4.3 Advisor 基类------BaseAdvisor
Advisor 的基类定义在 spring-ai-client-chat 中:
java
// 文件路径:spring-ai-client-chat(结构示意)
public interface BaseAdvisor extends CallAdvisor, StreamAdvisor {
// 同时支持同步和流式调用
// 提供 aroundCall 和 aroundStream 的 default 实现
// 在执行 chain 的 next 之前执行 before,之后执行 after 方法
}
public interface CallAroundAdvisor extends Advisor {
ChatClientResponse aroundCall(
ChatClientRequest request,
CallAroundAdvisorChain chain
);
}
设计模式解读 :BaseAdvisor 同时支持同步和流式调用,是适配器模式(Adapter Pattern) 的体现------它将同步和流式两种调用方式统一到同一个 Advisor 接口下。
4.4 ToolCallingAdvisor------递归 Advisor 的源码剖析
ToolCallingAdvisor 是 2.0 版本最核心的 Advisor 实现:
java
// 文件路径:spring-ai-client-chat(结构示意)
public class ToolCallingAdvisor implements CallAroundAdvisor {
private final ToolCallingManager toolCallingManager;
@Override
public ChatClientResponse aroundCall(
ChatClientRequest request,
CallAroundAdvisorChain chain
) {
// 1. 提取 @Tool 注解的方法 → 生成 Tool Definitions
List<ToolDefinition> tools = extractTools(request);
// 2. 将工具定义注入到请求中
request = request.withTools(tools);
// 3. 执行下游链
ChatClientResponse response = chain.next(request);
// 4. 检查响应是否包含工具调用
if (response.hasToolCalls()) {
// 5. 执行工具
List<ToolResult> results = toolCallingManager.execute(
response.getToolCalls()
);
// 6. 将工具结果追加到对话历史
// 7. 递归进入下游链
return reenterChain(request.withToolResults(results));
}
return response; // 无工具调用,返回最终答案
}
}
关键设计 :ToolCallingAdvisor 的 aroundCall 方法在检测到工具调用时会递归调用 chain.next(),实现"循环直到模型不再请求工具调用"的效果。DefaultChatClient 会自动将 ToolCallingAdvisor 添加到 Advisor 链中------同一时刻只能有一个 ToolAdvisor。
五、核心执行流程与运行时机制
5.1 执行流程------从 prompt 到响应
当你调用 chatClient.prompt("你好").call().content() 时,底层发生了什么?
┌─────────────────────────────────────────────────────────────────────┐
│ 1. 用户调用 chatClient.prompt("你好").call().content() │
│ ↓ │
│ 2. ChatClient.prompt() 创建 PromptRequestSpec │
│ ↓ │
│ 3. .call() 构建完整的 Prompt 对象 │
│ ├── UserMessage(用户输入) │
│ ├── SystemMessage(默认系统提示) │
│ └── Tool Definitions(来自 @Tool 注解的方法) │
│ ↓ │
│ 4. 执行 Advisor 链(洋葱模型,从外到内) │
│ ├── SimpleLoggerAdvisor → 记录请求日志 │
│ ├── MessageChatMemoryAdvisor → 加载历史消息 │
│ └── ToolCallingAdvisor → 注入 Tool Definitions │
│ ↓ │
│ 5. 调用 ChatModel.call(Prompt) → 发送给 AI 模型 │
│ ↓ │
│ 6. AI 模型返回 ChatResponse │
│ ↓ │
│ 7. 执行 Advisor 链(后置阶段,从内到外) │
│ ├── ToolCallingAdvisor → 检查是否有 tool calls │
│ │ ├── 有 → 执行工具 → 追加结果 → 回到步骤 4(递归)│
│ │ └── 无 → 继续 │
│ └── MessageChatMemoryAdvisor → 保存对话历史 │
│ ↓ │
│ 8. .content() 提取响应文本 → 返回给用户 │
└─────────────────────────────────────────────────────────────────────┘
图:Spring AI 的完整执行流程。Advisor 链是核心------请求从外到内穿透,响应从内到外返回。ToolCallingAdvisor 的递归机制让工具调用循环成为可能。
关键设计 :整个执行过程是Advisor 链驱动的 。ToolCallingAdvisor 的递归机制是 2.0 最大的创新------它将工具调用循环从"埋在模型实现里的私有逻辑"变成了"可组合、可观察的一等公民"。
5.2 工具调用循环的递归机制
ToolCallingAdvisor 的递归执行流程:
┌─────────────────────────────────────────────────────────────┐
│ 工具调用循环(递归 Advisor) │
│ │
│ ① 用户请求 + Tool Definitions → 发送给 LLM │
│ ↓ │
│ ② LLM 返回响应 │
│ ↓ │
│ ③ 检查是否包含 tool calls │
│ ├── 否 → 返回最终答案(停止) │
│ └── 是 → ToolCallingManager 执行工具 │
│ ↓ │
│ 将工具结果追加到对话历史 │
│ ↓ │
│ 重新进入 Advisor 链(回到步骤 ①)│
└─────────────────────────────────────────────────────────────┘
每轮迭代中,累积的对话历史(用户消息、AI 工具调用请求、工具响应)都会与当前上下文合并,再次发送给 LLM。
你可能会担心:如果 Agent 一直请求工具调用怎么办? ToolCallingAdvisor 内部有 maxIterations 保护,防止无限循环。
5.3 流式支持与异步处理
Spring AI 2.0 的 Advisor 管线同时支持阻塞(.call())和流式(.stream())模式:
java
// 流式调用
Flux<String> stream = chatClient.prompt("写一首诗")
.stream()
.content();
stream.subscribe(token -> {
// 逐字输出到前端(SSE/WebSocket)
});
流式模式下,Advisor 链的执行逻辑与阻塞模式一致,但每个 Advisor 都提供了 aroundStream 方法。ToolCallingAdvisor 在流式模式下采用顺序聚合模式------先聚合完整响应,再递归执行工具调用。
5.4 运行时关键决策的权衡分析
| 决策 | 方案 | 收益 | 代价 |
|---|---|---|---|
| 工具调用循环 | 递归 Advisor vs 模型私有循环 | 可组合、可观察、可扩展 | 递归实现复杂度高,Advisor 顺序至关重要 |
| 执行模型 | 同步 + 流式双模式 | 覆盖所有场景 | 两种模式需要维护两套 Advisor 接口 |
| 记忆管理 | Advisor 管线 vs 内置 | 可插拔、可组合 | 需要理解 Advisor 顺序才能正确配置 |
| 模型抽象 | 统一接口 vs 原生 SDK | 可移植性高 | 抽象层丢失部分特有配置 |
六、工程化实践
理论说完了,接下来咱们聊聊实战------用 Spring AI 搭建生产级应用时,你最关心的三个问题:怎么集成?怎么优化?有哪些坑?
6.1 快速接入
Maven 依赖:
xml
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
配置 (application.yml):
yaml
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: gpt-4
基础使用------ChatClient:
java
@RestController
public class ChatController {
@Autowired
private ChatClient chatClient;
@GetMapping("/chat")
public String chat(@RequestParam String message) {
return chatClient.prompt(message)
.system("你是一个博学的智能聊天助手")
.call()
.content();
}
}
6.2 自定义 Advisor 扩展
通过 Advisor 实现横切关注点:
java
@Component
public class LoggingAdvisor implements CallAroundAdvisor {
@Override
public ChatClientResponse aroundCall(
ChatClientRequest request,
CallAroundAdvisorChain chain
) {
log.info("请求: {}", request.getUserText());
long start = System.currentTimeMillis();
ChatClientResponse response = chain.next(request);
log.info("响应耗时: {}ms", System.currentTimeMillis() - start);
return response;
}
@Override
public int getOrder() {
return 0; // 控制 Advisor 执行顺序
}
}
6.3 RAG 集成
Spring AI 通过 RetrievalAugmentationAdvisor 提供开箱即用的 RAG 支持:
java
@Autowired
private VectorStore vectorStore;
@Bean
public ChatClient chatClient(ChatModel chatModel) {
return ChatClient.builder(chatModel)
.defaultAdvisors(
new RetrievalAugmentationAdvisor(vectorStore)
)
.build();
}
6.4 性能优化策略
(1)语义缓存
Spring AI 2.0 提供了基于 Redis 的语义缓存 Advisor------RedisSemanticCacheAdvisor,用于缓存语义相似的查询。
收益 :缓存命中时延迟可降低 50-80%,同时节省 API 调用费用。代价:需要 Redis 存储和语义相似度计算开销。
(2)流式响应提升用户体验
使用 .stream() 方法逐字输出:
java
Flux<String> stream = chatClient.prompt("写一首诗")
.stream()
.content();
stream.subscribe(token -> {
// 逐字输出到前端
});
收益 :用户看到模型"正在打字",感知延迟大幅降低。代价:流式响应的处理逻辑比普通调用更复杂。
(3)批处理与并行化
对于需要同时处理多个独立请求的场景,使用 Project Reactor 的并行能力:
java
List<Mono<String>> requests = messages.stream()
.map(msg -> Mono.fromCallable(() ->
chatClient.prompt(msg).call().content()
))
.collect(Collectors.toList());
List<String> results = Flux.merge(requests)
.collectList()
.block();
6.5 常见工程陷阱与解决方案
陷阱 1:Transformer 同步调用在异步流程中阻塞
现象 :在 RAG 工作流的 RetrievalAugmentationAdvisor 中使用 Transformer 时,出现阻塞或超时。
原因 :目前官方实现的所有 Transformer 都是同步(call() 模式)调用,如果作为组件串联在异步流程中会报错。
解决方案:官方不实现流式 Transformer 的原因是"对于功能性确定、不需要对用户展示的转化,实现流式几乎没有意义"。如果必须在异步流程中使用,需要自己实现流式 Transformer------但异步转同步的"假异步"方式耗时远超纯同步调用。
陷阱 2:Advisor 顺序错误导致逻辑失效
现象:记忆 Advisor 在工具调用循环中无法正确加载历史消息。
原因 :ToolCallingAdvisor 的默认顺序是 HIGHEST_PRECEDENCE + 300。记忆 Advisor 如果放在 ToolCallingAdvisor 内部,会在每次工具调用迭代中重复加载记忆。
解决方案 :DEFAULT_CHAT_MEMORY_PRECEDENCE_ORDER 已被降低,使记忆 Advisor 包裹工具调用循环而非参与每次迭代。理解 Advisor 的顺序约定是正确配置的前提。
陷阱 3:版本升级导致 API 变更
现象:从 1.0.0-M6 升级到 1.0.0 GA 或 2.0 时,代码编译失败。
原因:2.0 版本在工具注册、配置方式等方面与 1.x 存在显著差异。
解决方案:
- 升级前查阅官方迁移指南
- 注意 Spring AI 版本与 Spring Boot 版本的对应关系(2.0 需要 Spring Boot 4.0/4.1)
- 在生产环境中精确锁定版本,避免自动升级
七、总结与展望
7.1 关键版本里程碑
| 版本/事件 | 时间 | 核心变化 |
|---|---|---|
| 项目启动 | 2024 年 | Spring 官方 AI 项目启动 |
| 0.8.0 | 2024 年 2 月 | 首个里程碑版本 |
| 1.0.0 GA | 2025 年 | 首个稳定主版本 |
| 2.0.0 GA | 2026 年 6 月 12 日 | 最大版本升级 |
2.0 版本的核心变化:
| 变化 | 说明 |
|---|---|
| 工具调用成为一等公民 | Agent 循环更易于观察、组合和扩展 |
| MCP 原生集成 | 与 AI 模型交互的标准协议 |
| Jackson 3 序列化 | 从 Jackson 2 全面升级 |
| JSpecify 空安全 | 整个代码库使用 JSpecify 注解 |
| Options 体系重构 | 默认值统一在 Options 层定义,Options 不可变 |
| ChatClient 成为主角 | ChatModel 降级为底层构建块 |
7.2 横向对比:Spring AI vs LangChain4j vs Agents-Flex vs Spring AI Alibaba
7.2.1 可比性说明
Spring AI、LangChain4j、Agents-Flex、Spring AI Alibaba 均定位于 Java 生态的 LLM 应用开发框架,面向 Java/Spring 技术栈开发者。它们在功能定位上有重叠------都提供模型统一抽象、工具调用和 RAG 支持------但各自的设计哲学和擅长领域不同。
7.2.2 横向对比表
| 对比维度 | Spring AI | LangChain4j | Agents-Flex | Spring AI Alibaba |
|---|---|---|---|---|
| 核心定位 | AI 能力的 Spring 风格标准接口 | 组件最全的 Java AI 工具箱 | 无绑定、JDK8+ 的轻量 Agent 链 | 带 Graph 引擎的企业 Agent 平台 |
| 设计哲学 | 抽象与解耦(类似 JDBC 规范) | 声明式服务(接口+代理) | 轻量责任链 | Graph 工作流编排 |
| 核心抽象 | Model + ChatClient + Advisor | AiServices(声明式接口) | ChatModel + Interceptor 链 | Graph + Workflow |
| JDK 要求 | Java 17+ | Java 17+ | Java 8+ | Java 17+ |
| Spring 集成 | 官方原生 | 官方 Starter | 社区 Starter | 官方原生 + 阿里云生态 |
| 工具调用 | @Tool + ToolCallingAdvisor(递归) | @Tool + 手动循环 | @ToolDef | ReactAgent 内置 |
| 可观测性 | Spring 原生(Micrometer/OTel) | 有限 | OpenTelemetry | 全链路可观测 |
| MCP 支持 | ✅ 原生集成 | ✅ Client 端 | ✅ Client 端 | Client + Server 双端 |
| 版本状态 | 2.0.0 GA(2026.6) | 1.18.1(2026.8) | 2.2.4(2026.7) | 1.1.2.2(2026.8) |
7.2.3 差异来源分析
| 框架 | 核心判断 | 架构推论 |
|---|---|---|
| Spring AI | Java 开发者最熟悉 Spring 的抽象方式(JDBC/JPA 模式) | 用 Model/ChatClient 提供统一抽象,与 Spring 生态深度绑定 |
| LangChain4j | Java 开发者最习惯"声明接口,框架实现"的模式 | AiServices + 动态代理,像 Spring Data JPA 一样声明式编程 |
| Agents-Flex | 很多 Java 老系统还在用 JDK 8,不能强求升级 | Core 模块兼容 Java 8,轻量无绑定 |
| Spring AI Alibaba | Agent 是业务工作流,需要平台化治理 | 在 Spring AI 之上叠加 Graph 引擎和治理平台 |
7.2.4 结论性建议
| 场景 | 推荐选择 | 核心理由 |
|---|---|---|
| 已有 Spring Boot 项目,想低风险接入 AI | Spring AI | 官方出品,与 Spring Boot 4.x 同步演进,治理最顺 |
| 需要复杂编排、模型切换频繁 | LangChain4j | 组件最全,可自由组合 |
| 老旧系统(JDK 8)需要接入 AI | Agents-Flex | Core 模块兼容 Java 8,无框架绑定 |
| 需要企业级工作流编排和多 Agent 平台 | Spring AI Alibaba | Graph 引擎 + 可视化开发平台 + 阿里云生态 |
7.3 设计哲学提炼
Spring AI 的设计哲学可以提炼为三个关键词:
-
抽象即自由 :正如
JdbcTemplate统一了数据库访问,Spring AI 在 AI 领域建立了一套通用编程模型 -
管线即编排:Advisor 责任链将横切逻辑统一收编,2.0 更进一步将工具调用循环也纳入管线
-
渐进式复杂度 :从底层的
ChatModel到高层的ChatClient和 Advisor 链,开发者可按需选择抽象层级
7.4 核心架构亮点
| 亮点 | 说明 |
|---|---|
| Model/ChatClient 分层 | 策略模式 + 门面模式,15+ AI 提供商一键切换 |
| Advisor 责任链 | 洋葱模型执行,日志/记忆/RAG/工具调用统一装配 |
| ToolCallingAdvisor 递归 | 2.0 核心创新,将工具循环从黑盒变为可组合的一等公民 |
| @Tool 注解驱动 | 反射自动生成 JSON Schema,与 Spring MVC 风格一致 |
| MCP 原生集成 | 与 AI 模型交互的标准协议 |
| Spring 生态无缝集成 | 依赖注入、自动配置、Micrometer/OTel 可观测 |
7.5 对开发者的启示与适用场景
Spring AI 的本质不是又一套 AI SDK 封装,而是一套以"Spring 风格的标准接口"为设计哲学、以"Advisor 责任链"为编排管线、将"工具调用循环"从模型内部私有逻辑升级为可组合、可观测、可递归的一等公民的 Java AI 开发框架------让 Spring 开发者像操作普通 Service 一样操作大模型,像写 Spring AOP 一样编排 AI 工作流。
适用场景:
- 已有 Spring Boot 项目,想低风险地把 AI 能力集成进去
- 需要集成多个 AI 模型提供商的企业级应用
- 需要对话记忆、RAG、工具调用等高级特性的 Spring 应用
- 需要与 Spring 生态深度集成(依赖注入、可观测、安全)的生产系统
不适用场景:
- 非 Spring 生态的 Java 项目(可考虑 LangChain4j 或 Agents-Flex)
- 对延迟极度敏感、不能接受框架开销的场景
- 需要 Python 生态特有库(如 Hugging Face transformers)的场景
- JDK 8 及以下的老旧系统(Agents-Flex 更适合)
本文数据来源:Spring AI 官方文档、Spring 官方博客、GitHub Releases、Spring AI 2.0 GA 公告、Agent 框架对比文章(截至 2026 年 8 月)
如您所在的企业正面临数字化难题,或有 AI 落地、系统集成相关需求,欢迎进一步沟通。我们可提供针对贵企业具体场景的定制化方案和现场调研服务。