Spring AI 2.0 架构重构深度解析:从单体核心到模块化领域的演进
一、架构重构的背景与必要性
Spring AI 2.0并非简单的版本号迭代,而是一次架构哲学的根本转变。在1.x时代,Spring AI采用相对集中的单体架构设计,随着AI模型生态的爆发式增长(从大语言模型到嵌入模型、从图像生成到向量存储),原有的spring-ai-core包已膨胀至难以维护的地步。
Spring AI 2.0.0-M1版本彻底摒弃了单体模式,转而采用领域驱动模块化(Domain-Driven Modularization)策略,将AI能力按技术边界拆分为五个核心领域模块。这一重构不仅契合Spring Boot 4.0自身的模块化趋势,更为企业级AI应用提供了更精细的依赖治理能力。
二、模块化架构的核心依赖链
Spring AI 2.0的模块设计遵循严格的分层依赖原则,底层模块禁止向上依赖,形成清晰的无环有向图(DAG)。以下是核心模块的依赖拓扑结构:
md
┌─────────────────────────────────────────────────────────────┐
│ 应用层 (Application) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ RAG应用 │ │ ChatClient │ │ Function │ │
│ │ 模块 │ │ 应用层 │ │ Call应用 │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
└─────────┼─────────────────┼─────────────────┼───────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ 客户端抽象层 (Client Abstraction) │
│ spring-ai-client-chat (对话客户端) │
│ 依赖: spring-ai-model │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 模型抽象层 (Model Abstraction) │
│ spring-ai-model (核心模型接口) │
│ 依赖: spring-ai-commons │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 基础设施层 (Infrastructure) │
│ spring-ai-commons (基础工具与接口) │
│ 零外部依赖 (Zero Dependencies) │
└─────────────────────────────────────────────────────────────┘
▲
│
┌──────────────────────────┴──────────────────────────────────┐
│ 存储抽象层 (Storage Abstraction) │
│ spring-ai-vector-store (向量存储抽象) │
│ 依赖: spring-ai-commons │
└─────────────────────────────────────────────────────────────┘
关键设计约束:
- spring-ai-commons作为唯一的基础层,禁止依赖任何上层模块
- spring-ai-model仅依赖commons,定义ChatModel/EmbeddingModel等核心接口
- spring-ai-client-chat依赖model层,提供ChatClient的Fluent API实现
- Vector Store模块独立存在,通过Advisor机制与Client层桥接
三、领域模块的职责边界与定位
| 模块名称 | Maven坐标 | 职责边界 | 是否必须 |
|---|---|---|---|
| spring-ai-commons | org.springframework.ai:spring-ai-commons |
定义AI领域的通用领域模型(Message、Prompt、Media等),提供跨模型的可复用数据结构 | 是(所有模块依赖) |
| spring-ai-model | org.springframework.ai:spring-ai-model |
定义模型调用抽象接口(ChatModel、EmbeddingModel、ImageModel),实现可移植的Options模式 |
是(核心依赖) |
| spring-ai-client-chat | org.springframework.ai:spring-ai-client-chat |
提供ChatClient及Advisor机制,支持函数调用、多模态、RAG等高级功能 |
否(仅高级应用需要) |
| spring-ai-vector-store | org.springframework.ai:spring-ai-vector-store |
统一向量数据库的CRUD抽象,支持PgVector、Redis、Milvus等实现 | 否(RAG场景需要) |
| spring-ai-advisors-vector-store | org.springframework.ai:spring-ai-advisors-vector-store |
桥接ChatClient与Vector Store,实现QuestionAnswerAdvisor等RAG组件 |
否(显式RAG需要) |
架构师视角解读:
这种拆分使得仅使用基础模型调用能力的应用无需引入client-chat层的复杂性。例如,一个仅需调用OpenAI API进行简单问答的微服务,只需依赖spring-ai-model和具体模型实现(如spring-ai-openai),而不必引入整个Client生态。
四、Jakarta EE 11 基线迁移与兼容性
Spring AI 2.0将技术基线全面迁移至Jakarta EE 11 + Spring Boot 4.0 GA + Spring Framework 7.0,这对企业现有系统产生深远影响:
4.1 强制性环境要求
md
┌──────────────────────────────────────────────────────┐
│ 基线版本对比 │
├──────────────────┬──────────────────┬────────────────┤
│ 组件 │ Spring AI 1.x │ Spring AI 2.0 │
├──────────────────┼──────────────────┼────────────────┤
│ Java版本 │ 17+ │ 21(强制) │
│ Spring Boot │ 3.x │ 4.0 GA │
│ Spring Framework│ 6.x │ 7.0 │
│ Jakarta EE │ 9/10 │ 11 │
│ Servlet │ 6.0 │ 6.1 │
│ JPA │ 3.1 │ 3.2 │
└──────────────────┴──────────────────┴────────────────┘
迁移红利:
- 虚拟线程(Virtual Threads):默认启用,单个线程可承载数万AI对话会话
- AOT编译优化:Native Image支持AI模型的提前编译,启动速度提升3-5倍
- GraalVM 25:统一可达性元数据格式,减少反射配置复杂度
4.2 破坏性变更清单
包命名空间迁移(关键变更):
java
// 1.x 旧包路径(已废弃)
import org.springframework.ai.transformer.KeywordMetadataEnricher;
import org.springframework.ai.model.Content;
// 2.x 新包路径
import org.springframework.ai.chat.transformer.KeywordMetadataEnricher;
import org.springframework.ai.content.Content;
Starter命名规范变更:
xml
<!-- 1.x 旧坐标 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
<!-- 2.x 新坐标(遵循Spring Boot 4模块化规范) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
配置属性重命名:
properties
# 1.x
spring.ai.openai.include-prompt=true
spring.ai.chat.memory.redis.ttl=3600
# 2.x
spring.ai.openai.log-prompt=true
spring.ai.chat.memory.repository.redis.ttl=3600
五、依赖注入范式:ChatModel vs 旧版ModelClient
Spring AI 2.0最核心的API重构在于调用范式的分层。旧版ModelClient被彻底重命名为ChatModel,而新的ChatClient则成为基于ChatModel的高级封装层。
5.1 架构分层模型
md
┌─────────────────────────────────────────────────────────────┐
│ ChatClient (高级API) │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ 职责:Fluent API、Advisor链、函数调用、多模态支持 │ │
│ │ 定位:应用层开发首选,类似RestClient/WebClient │ │
│ └───────────────────────────────────────────────────────┘ │
└───────────────────────────┬─────────────────────────────────┘
│ 组合
▼
┌─────────────────────────────────────────────────────────────┐
│ ChatModel (基础API) │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ 职责:模型调用的可移植抽象,call(Prompt)/stream(Prompt)│ │
│ │ 定位:基础设施层,类似JDBC的DataSource │ │
│ └───────────────────────────────────────────────────────┘ │
└───────────────────────────┬─────────────────────────────────┘
│ 实现
▼
┌─────────────────────────────────────────────────────────────┐
│ OpenAiChatModel / OllamaChatModel │
│ (具体模型实现) │
└─────────────────────────────────────────────────────────────┘
5.2 编程范式对比
ChatModel模式(基础层):
适合需要精细控制或轻量级集成的场景,如简单的HTTP接口代理。
java
@RestController
public class SimpleChatController {
@Autowired
private ChatModel chatModel; // 直接注入基础接口
@GetMapping("/simple-chat")
public String chat(@RequestParam String message) {
// 函数式调用,一行代码完成
return chatModel.call(message);
}
@GetMapping(value = "/stream-chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> stream(@RequestParam String message) {
// 流式响应直接返回
return chatModel.stream(message);
}
}
ChatClient模式(应用层):
适合复杂对话管理、RAG、函数调用等企业级场景。
java
@Service
public class AdvancedChatService {
private final ChatClient chatClient;
// 通过构造器注入并配置默认选项
public AdvancedChatService(ChatModel chatModel) {
this.chatClient = ChatClient.builder(chatModel)
.defaultOptions(ChatOptions.builder()
.model("gpt-4")
.temperature(0.7)
.maxTokens(2000)
.build())
.build();
}
public String chatWithMemory(String sessionId, String message) {
return chatClient.prompt()
.system("你是资深Java架构师助手") // 系统提示
.user(message) // 用户输入
.advisors(new MessageChatMemoryAdvisor( // 记忆Advisor
new InMemoryChatMemory(),
sessionId,
10
))
.functions("queryOrderStatus") // 函数调用
.call()
.content();
}
}
5.3 选型决策树
md
是否需要函数调用/工具使用?
├── 是 → 必须使用 ChatClient
│ └── 是否需要多轮对话记忆?
│ ├── 是 → ChatClient + MessageChatMemoryAdvisor
│ └── 否 → ChatClient + 默认配置
└── 否 → 是否需要RAG/向量检索?
├── 是 → ChatClient + QuestionAnswerAdvisor
└── 否 → 性能敏感?
├── 是 → ChatModel (减少一层代理开销)
└── 否 → ChatClient (更好的可维护性)
六、多模块Maven配置与依赖排除策略
在Spring AI 2.0的多模块架构下,合理的依赖管理是避免传递依赖地狱的关键。
6.1 典型项目依赖配置
xml
<properties>
<java.version>21</java.version>
<spring-boot.version>4.0.0</spring-boot.version>
<spring-ai.version>2.0.0-M1</spring-ai.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- 基础模型能力(必须) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-model</artifactId>
</dependency>
<!-- OpenAI模型实现(按需) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<!-- 高级客户端API(可选,但推荐) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-client-chat</artifactId>
</dependency>
<!-- 向量存储(RAG场景) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-redis</artifactId>
</dependency>
</dependencies>
6.2 依赖排除实战场景
场景一:排除特定模型实现,避免starter传递依赖
当使用自定义的ChatModel实现(如内部私有大模型)时,需要排除默认的OpenAI依赖:
xml
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-client-chat</artifactId>
<exclusions>
<!-- 排除默认的OpenAI自动配置 -->
<exclusion>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-autoconfigure</artifactId>
</exclusion>
</exclusions>
</dependency>
场景二:解决vector-store与client-chat的循环依赖风险
虽然官方已消除包之间的循环依赖,但在复杂项目中仍需注意:
java
@Configuration
@ConditionalOnClass({VectorStore.class, ChatClient.class})
public class RAGConfiguration {
// 显式通过方法参数注入,而非字段注入,避免初始化顺序问题
@Bean
public QuestionAnswerAdvisor questionAnswerAdvisor(VectorStore vectorStore) {
return new QuestionAnswerAdvisor(vectorStore);
}
}
场景三:模块化测试配置
在单元测试中仅加载必要的模块,避免完整的Spring Boot上下文:
java
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {
// 仅加载commons和model层,不加载client层
CommonsConfiguration.class,
OpenAiModelConfiguration.class
})
public class ModelLayerUnitTest {
// 测试ChatModel接口实现...
}
七、迁移策略与兼容性建议
对于正在使用Spring AI 1.x的企业级应用,建议采用分阶段迁移策略:
- 阶段一:基线升级(1-2周)
将JDK升级至Java 21(Spring AI 2.0强制要求)
升级Spring Boot至4.0.x,解决Jakarta EE 11命名空间冲突
更新所有javax.导入为jakarta. - 阶段二:API迁移(2-3周)
优先迁移:将旧版ModelClient调用点改为ChatModel
渐进增强:在复杂业务场景中引入ChatClient替代原生Prompt构造
配置更新:按照新命名规范更新application.yml - 阶段三:模块化重构(1周)
梳理项目中实际使用的AI能力(仅对话?需要RAG?)
移除未使用的starter依赖(如未使用向量存储则移除spring-ai-starter-vector-store-redis)
利用新的模块化边界,拆分过大的AI服务模块
高风险变更点 checklist: - MessageAggregator类已迁移至spring-ai-model模块,但aggregateChatClientResponse方法已移至ChatClientMessageAggregator
- ChatMemory接口常量变更:CHAT_MEMORY_CONVERSATION_ID_KEY → CONVERSATION_ID,CHAT_MEMORY_RETRIEVE_SIZE_KEY → TOP_K
- 工具调用API变更:tools()方法已重命名为toolSpecifications()
- 移除的模型:Watson、Moonshot、QianFan已移至社区仓库
八、总结
Spring AI 2.0的模块化重构并非简单的代码重组,而是对AI工程化复杂度的战略回应。通过commons → model → client-chat的清晰分层,开发者得以在轻量级集成与企业级能力之间做出精确权衡。
对于架构师而言,这一变化要求重新评估AI能力在系统中的依赖边界。建议新 projects 直接采用ChatClient + 按需模块依赖的模式,而遗留系统则应制定分阶段迁移路线,优先解决Java 21与Jakarta EE 11的兼容性基线问题。
本文章基于SpringAI官方文档学习撰写。仅供学习参考,请勿用于商业用途。