Spring AI vs LangChain4j:Java 后端接大模型,两条路线怎么选
Spring AI vs LangChain4j:Java 后端接大模型,两条路线怎么选
Java 世界里接入大模型,现在有两个正经选择:Spring 官方的 Spring AI,和社区驱动的 LangChain4j。前者 8795 star,后者 12113 star。数字差不多,但设计哲学完全两回事。
这篇文章不讲 Hello World,从核心抽象、记忆管理、RAG、Function Calling 几个维度掰开看,帮你搞清楚什么时候用哪个。
目录
- 一、为什么 Spring 要自己做 AI?
- 二、核心抽象:ChatClient vs AiServices
- 三、记忆管理:Advisors vs ChatMemory
- 四、RAG 方案对比
- 五、Function Calling:AI 怎么调用你的代码
- 六、生态与可观测性
- 七、选型建议
一、为什么 Spring 要自己做 AI?
LangChain4j 比 Spring AI 早出来不少,Star 数也更高。那 Spring 为什么还要单开一局?
三个原因。
第一,Spring 生态有自己的做事方式。 Spring 开发者习惯了依赖注入、自动配置、Actuator 端点、Micrometer 指标。LangChain4j 虽然也能集成 Spring Boot,但它不是 Spring 原生设计的,集成的"Spring 味"始终差一点。
第二,Spring AI 想覆盖的不止是 LLM 调用。 它的范围更接近"AI 工程化的 Spring 答案":模型接入、向量存储、ETL 管道、MCP 协议支持、可观测性——这些在 LangChain4j 里要么没有,要么靠社区补。
第三,企业级需求。 Spring 在企业市场根深蒂固。Spring AI 自带 Actuator health check、Micrometer 埋点、AOT 编译支持,这些东西 LangChain4j 做起来要额外踩坑。
一句话:LangChain4j 是"让 Java 能用 LangChain",Spring AI 是"让 Spring 开发者用 AI 跟用数据库一样自然"。 定位不同。
二、核心抽象:ChatClient vs AiServices
这是两个框架最根本的分歧点。
Spring AI:ChatClient
Spring AI 的核心入口是 ChatClient,一个 fluent builder 风格的 Bean。用法跟 RestClient 和 JdbcClient 一脉相承:
@Bean
ChatClient chatClient(ChatModel chatModel) {
return ChatClient.builder(chatModel).build();
}
// 使用
String answer = chatClient.prompt()
.user("这个项目用什么构建工具?")
.call()
.content();
思路很 Spring:你拿到一个注入好的 Bean,链式调用,请求返回。Advisors(类似拦截器)在调用链路中插入逻辑:
chatClient.prompt()
.user("这个项目用什么构建工具?")
.advisors(new MessageChatMemoryAdvisor(chatMemory))
.call()
.content();
你的代码里自始至终只有一个对象:ChatClient。记忆、RAG、日志这些横切关注点通过 Advisors() 链上去。接触过 Spring AOP 的人一秒就能理解。
LangChain4j:AiServices
LangChain4j 的核心入口是 AiServices,走接口代理路线。你声明一个接口,框架给你生成实现:
interface ProjectAssistant {
@SystemMessage("你是项目技术顾问,回答基于项目实际配置")
String chat(String userMessage);
}
ProjectAssistant assistant = AiServices.builder(ProjectAssistant.class)
.chatLanguageModel(model)
.chatMemory(MessageWindowChatMemory.withMaxMessages(10))
.build();
String answer = assistant.chat("这个项目用什么构建工具?");
你围绕业务语义组织代码:ProjectAssistant、CodeReviewer、DocWriter,每个接口代表一个角色。LangChain4j 在背后生成代理对象,把记忆、工具调用都绑在接口上。
核心差异
| 维度 | Spring AI ChatClient | LangChain4j AiServices |
|---|---|---|
| 编程模型 | Fluent Builder + Bean 注入 | 接口声明 + 动态代理 |
| 组织方式 | 围绕调用链组织代码 | 围绕业务角色组织接口 |
| 横切关注点 | Advisors 链(类 AOP) | 绑定在 Builder 上 |
| 学习曲线 | Spring 开发者零门槛 | 需要适应接口代理思维 |
| 灵活性 | 每次调用都可以动态组合 Advisors | 接口定义时就绑定了行为 |
选哪个更多是口味问题。习惯 Spring 的 xxxClient 系列就用 ChatClient,喜欢按业务角色拆分接口就用 AiServices。
三、记忆管理:Advisors vs ChatMemory
对话记忆是 AI 应用里最容易做砸的地方。两个框架给出了完全不同的解法。
Spring AI:Advisors 模式
Spring AI 把记忆当作一个横切关注点,通过 Advisors 注入:
// 基于消息数量的窗口记忆
ChatMemory chatMemory = new InMemoryChatMemory();
MessageChatMemoryAdvisor memoryAdvisor =
new MessageChatMemoryAdvisor(chatMemory);
// 基于 Token 数量的窗口记忆
TokenStreamChatMemory tokenMemory =
new TokenStreamChatMemory(4096);
MessageChatMemoryAdvisor tokenAdvisor =
new MessageChatMemoryAdvisor(tokenMemory);
chatClient.prompt()
.user("帮我查一下昨天的订单")
.advisors(memoryAdvisor) // 记忆作为一个 Advisor 插入
.call()
.content();
Advisors 是按顺序执行的。你可以链上多个:
chatClient.prompt()
.user("帮我查一下昨天的订单")
.advisors(memoryAdvisor, loggingAdvisor, ragAdvisor)
.call()
.content();
顺序敏感,排在前面的先执行。这个设计的优势是组合自由:记忆、RAG、日志、权限检查可以任意排列,每个 Advisors 职责单一。
LangChain4j:ChatMemory 接口
LangChain4j 把记忆绑在 AiServices Builder 上,或者手动管理:
// 方式一:绑在 AiServices 上
ChatMemory memory = MessageWindowChatMemory.withMaxMessages(10);
ProjectAssistant assistant = AiServices.builder(ProjectAssistant.class)
.chatLanguageModel(model)
.chatMemory(memory)
.build();
// 方式二:手动管理
List<ChatMessage> history = new ArrayList<>();
history.add(SystemMessage.from("你是项目技术顾问"));
history.add(UserMessage.from("这个项目用什么构建工具?"));
history.add(AiMessage.from("用 Maven"));
history.add(UserMessage.from("为什么不是 Gradle?"));
Response<AiMessage> response = model.generate(history);
LangChain4j 提供了多种记忆实现:
// 按消息数量截断
MessageWindowChatMemory.withMaxMessages(10);
// 按 Token 数量截断
TokenWindowChatMemory.withMaxTokens(2000, new OpenAiTokenizer());
差异点
Spring AI 的 Advisors 模式给了你一个插拔式的记忆管道,记忆只是管道中的一个切面。LangChain4j 把记忆作为 ChatModel 调用的一部分,更直接但组合性稍弱。
如果说 Spring AI 的记忆像 Spring Security 的 Filter Chain,LangChain4j 的记忆更像一个带截断的消息列表。
四、RAG 方案对比
RAG 是 AI 应用里最实用的模式:把私有文档喂给 AI,让它基于你的数据回答问题。两个框架都有完整方案,但实现路径不同。
Spring AI:ETL 管道
Spring AI 把文档处理拆成标准的 ETL 三步:
DocumentReader → DocumentTransformer → DocumentWriter
// 1. 读取文档
DocumentReader reader = new JsonReader(fileSystemResourceLoader);
List<Document> documents = reader.read();
// 2. 切分文档
DocumentTransformer splitter =
new TokenTextSplitter(800, 100, 5, 10000, true);
List<Document> chunks = splitter.transform(documents);
// 3. 写入向量数据库
VectorStore vectorStore =
new PgVectorStore(dataSource, new JdbcTemplate(dataSource));
vectorStore.add(chunks);
查询时用 QuestionAnswerAdvisor:
chatClient.prompt()
.user("Spring AI 怎么配置向量数据库?")
.advisors(new QuestionAnswerAdvisor(vectorStore))
.call()
.content();
优点是把 ETL 拆成独立步骤,替换任意一环都很方便。换一个文档格式?只换 Reader。换一种切分策略?只换 Transformer。换一个向量数据库?只换 VectorStore。
LangChain4j:EmbeddingStore + ContentRetriever
LangChain4j 没有显式的 ETL 管线概念,而是通过组件拼装:
// 文档摄入
EmbeddingStore<TextSegment> embeddingStore =
new InMemoryEmbeddingStore<>();
EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
.documentSplitter(DocumentSplitters.recursive(800, 100))
.embeddingModel(embeddingModel)
.embeddingStore(embeddingStore)
.build();
ingestor.ingest(document);
// 检索
ContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(embeddingStore)
.embeddingModel(embeddingModel)
.maxResults(5)
.minScore(0.75)
.build();
// 连上 AiServices
ProjectAssistant assistant = AiServices.builder(ProjectAssistant.class)
.chatLanguageModel(model)
.contentRetriever(retriever)
.build();
如果你不想手动拼,LangChain4j 还有 EasyRag:
EasyRag easyRag = EasyRag.builder()
.documentsPath("/data/docs")
.embeddingModel(embeddingModel)
.embeddingStore(embeddingStore)
.chatLanguageModel(model)
.build();
// 直接问
String answer = easyRag.chat("Spring AI 怎么配置向量数据库?");
差异
| 维度 | Spring AI | LangChain4j |
|---|---|---|
| 文档处理 | 显式 ETL 管线 (Reader/Transformer/Writer) | 内聚的 Ingestor |
| 检索接入 | Advisors 注入 | AiServices Builder 绑定 / EasyRag |
| 替换灵活性 | 每步独立 Bean,替换方便 | 组件粒度高,替换也不难 |
| 最简路径 | 需要配三步 | EasyRag 一行配置 |
Spring AI 的 ETL 模型更适合对文档处理流程有精细控制的场景。LangChain4j 的 EasyRag 适合快速原型。
五、Function Calling:AI 怎么调用你的代码
让 AI 调用你的业务代码,而不是光聊天。这是 Agent 的入口。两个框架都支持,写法也很像,但背后的注册机制不同。
Spring AI:Bean 方法注册
定义 @Tool,注入 ChatClient,自动发现:
@Component
public class OrderTools {
@Tool(description = "根据订单号查询订单状态")
public OrderStatus getOrderStatus(
@ToolParam(description = "订单号") String orderId) {
return orderService.findStatus(orderId);
}
@Tool(description = "取消指定订单")
public String cancelOrder(
@ToolParam(description = "订单号") String orderId) {
orderService.cancel(orderId);
return "已取消";
}
}
// ChatClient 自动发现所有 @Tool Bean
chatClient.prompt()
.user("帮我查一下 ORD-2024001 的状态")
.tools(orderTools) // 指定工具 Bean
.call()
.content();
AI 模型收到用户问题后,判断需要调用 getOrderStatus,提取参数 ORD-2024001,Spring AI 帮你调用 Bean 方法,把返回结果送回模型生成最终回复。
LangChain4j:接口方法上的 @Tool
class OrderTools {
@Tool("根据订单号查询订单状态")
public OrderStatus getOrderStatus(
@P("订单号") String orderId) {
return orderService.findStatus(orderId);
}
@Tool("取消指定订单")
public String cancelOrder(@P("订单号") String orderId) {
orderService.cancel(orderId);
return "已取消";
}
}
// 绑定到 AiServices
ProjectAssistant assistant = AiServices.builder(ProjectAssistant.class)
.chatLanguageModel(model)
.tools(new OrderTools())
.build();
String result = assistant.chat("帮我查一下 ORD-2024001 的状态");
差异点
| 维度 | Spring AI | LangChain4j |
|---|---|---|
| 工具注册 | Spring Bean 自动发现 | 手动传入 tools() |
| 参数注解 | @ToolParam | @P |
| 执行模型 | 框架自动调用 Bean | 框架反射调用对象方法 |
| 与 DI 集成 | 天然集成,工具可以是注入的 Bean | 需手动传实例 |
这个维度差距不大。Spring AI 对 Spring 开发者更顺手(工具就是 Bean),LangChain4j 对非 Spring 场景更友好(不依赖 DI 容器)。
六、生态与可观测性
Spring AI:Spring 全家桶
Spring AI 的最大优势不在 AI 功能本身,在它跟 Spring 生态的无缝衔接:
# 一行配置接入模型
spring:
ai:
openai:
api-key:
chat:
options:
model: gpt-4o
自动配置好了。要监控?
management:
endpoints:
web:
exposure:
include: health,metrics
Spring AI 的 ChatClient 调用自动接入 Micrometer,token 消耗、调用延迟、错误率直接出现在 Grafana 面板上。AOT 编译支持意味着可以编译成 GraalVM native image,启动速度从秒级压到毫秒级。
MCP(Model Context Protocol)支持也是 Spring AI 先做的。把一个外部 MCP Server 注册成 Spring Bean,ChatClient 直接调用它的工具,不用写一行胶水代码。
LangChain4j:社区驱动
LangChain4j 支持的模型厂商更多(30+),包括一些 Spring AI 还没覆盖的国内模型。Quarkus 和 Micronaut 集成也是 LangChain4j 的优势区。
但可观测性弱一些。Micrometer 集成存在但不成熟,没有原生的 AOT 支持,Actuator 端点需要自己实现。
| 维度 | Spring AI | LangChain4j |
|---|---|---|
| 模型接入数 | 20+ (OpenAI、Azure、Ollama…) | 30+ (覆盖面更广) |
| Spring Boot 集成 | 原生 (Starter + AutoConfig) | 通过 langchain4j-spring-boot-starter |
| 可观测性 | 原生 Micrometer + Actuator | 有集成但不够成熟 |
| AOT / Native Image | ✅ 支持 | ❌ 暂无 |
| MCP 协议 | ✅ 原生支持 | ⚠️ 社区插件 |
| 其他框架 | 仅 Spring | Quarkus、Micronaut |
七、选型建议
没标准答案,看场景。
选 Spring AI 的情况:
- 项目已经在 Spring Boot 生态里
- 团队习惯了 Spring 那套 DI + AutoConfig 的开发方式
- 需要 Actuator 监控、Micrometer 指标、GraalVM native image
- 想做 MCP 集成(让 AI 调用外部工具服务)
- 需要细粒度控制文档 ETL 管道
选 LangChain4j 的情况:
- 项目不是 Spring 生态(Quarkus、Micronaut、纯 Java)
- 需要接的模型 Spring AI 还没支持
- 团队偏好 AiServices 的接口代理风格
- 想做快速原型,EasyRag 一行配置搞定 RAG
- 看重社区活跃度和模型覆盖面
两个一起用:
技术上完全可行。LangChain4j 接入模型 + Spring AI 做可观测和部署,或者 Spring AI 做核心链路 + LangChain4j 补缺失的模型适配器。但增加了版本管理和调试成本,不推荐一开始就这么搞。
我个人倾向于:Spring 项目用 Spring AI,非 Spring 项目用 LangChain4j。 简单粗暴,但管用。
参考资料
- Spring AI 官方文档
- LangChain4j 官方文档
- Spring AI GitHub (8.8k stars)
- LangChain4j GitHub (12.1k stars)
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)