Spring之父Rod Johnson携Embabel归来:Java程序员的Agent时代正式开启
2026/9/10 23:51:11 网站建设 项目流程

title: "Spring之父Rod Johnson携Embabel归来:Java程序员的Agent时代正式开启" description: "Rod Johnson——那个写出Spring、把Java从EJB泥潭里救出来的男人,带着全新的Java Agent框架Embabel回来了。用GOAP算法做确定性规划、强类型Action、Spring原生集成,Java程序员不用转Python也能写生产级Agent。" tags: [Java, Agent, Spring, Embabel, AI工程化, Rod Johnson] image: "./images/embabel-rod-johnson-java-agent-cover.jpg"


Spring之父Rod Johnson携Embabel归来:Java程序员的Agent时代正式开启

开篇:「Java已死」这句话,我听了快十五年了。每次技术变革都有人念一遍——微服务时代念过一次,云原生时代念过一次,现在AI时代又有人拿出来说。但有意思的是,每次喊「Java不行了」的时候,总有一个人站出来给Java续上十年命。上一次是2002年的Spring,这一次,是2026年的Embabel。


一、从EJB到Agent:历史总是惊人地相似

1.1 当年Rod Johnson干了什么

如果你是个有十年以上工龄的Java老炮,应该对EJB这个词有心理阴影。零几年的时候,企业级Java的「官方标准答案」就是EJB。写一个业务组件,得继承一堆接口,配一堆XML,部署一次等半天。那时候说Java臃肿、说Java要完,真不是造谣,是实打实的难用。

2002年,一个叫Rod Johnson的澳洲人写了本书,叫《Expert One-on-One J2EE Design and Development》。书的核心观点就一句话:官方那套不行,我给你们写个更好的。书里附的那套代码,后来长成了Spring Framework。

Spring干的事很简单:普通Java对象(POJO)就能干活,不用继承什么特定接口,配置简单,测试好写。然后呢?然后Spring赢了,EJB那套直接被扫进了历史的垃圾堆。再往后Spring Boot、Spring Cloud一路铺开,全家桶把企业Java的命一路续到今天。

说Spring给Java续命十年,一点都不夸张。

1.2 今天的处境,和当年太像了

说回现在。打开GitHub搜Agent框架,LangChain、LangGraph、CrewAI、AutoGPT……清一色Python。公司要做AI,不少技术负责人的第一反应也是招Python的人,或者让Java的人去学。

我自己是Java出身,写了十几年Spring。这两年看着Python圈热热闹闹,说心里没落差是假的。不是说Python不好,但你让一个写了十年Java、对JVM生态门儿清的工程师,转头去跟Python的动态类型、缩进语法、虚拟环境打交道,那酸爽谁试谁知道。

Rod Johnson在访谈里聊到这事的时候,火气比我还大。他说很多人爱拿Java当靶子,假装这门语言二十年没动过。但他倒也没把Python框架贬得一文不值,原话很公允:

「那些框架不差,但JVM上有它们给不了的东西——几十年攒下来的类型安全的业务代码,成熟的IDE和重构工具,还有一大群写Java顺手、写Python别扭的工程师。」

这句话我深以为然。Java的护城河从来不是语言本身,是生态、是工具链、是几千万开发者积累的最佳实践。


二、Embabel的核心思路:规划这件事,不让大模型碰

2.1 从游戏行业借来的GOAP算法

Embabel最核心的设计,是从游戏行业借来的一个算法——GOAP(Goal-Oriented Action Planning,目标导向行动规划)。早年是给游戏里的NPC规划行为用的,比如《F.E.A.R.》里的敌人AI,用的就是这套东西。

我第一次看到的时候挺意外的,没想到一个Java Agent框架会跑去游戏行业找答案。但仔细一想,这招真的妙。

用GOAP写Agent,你只定义两样东西:

  • Action:Agent能干的每个动作
  • Goal:最终要达成什么目标

动作按什么顺序串,不用你写死,也不是大模型现场拍的,是框架里的规划器(Planner)算出来的。每执行完一步,它根据最新的状态重新算一遍,再决定下一步。

Embabel GOAP 工作流程: ┌─────────────────────────────────────────────────────┐ │ Goal(目标) │ │ "写一篇技术博客并审校发布" │ └──────────────────────────┬──────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────┐ │ Planner(确定性规划器) │ │ 输入:当前状态 + 可用Actions + Goal │ │ 输出:Action 执行序列(A*搜索算法) │ │ 特点:不调大模型,纯代码计算,可复现、可审计 │ └──────────────────────────┬──────────────────────────┘ ↓ ┌────────────────┴────────────────┐ ↓ ↓ ┌───────────────────┐ ┌───────────────────┐ │ Action 1: 调研 │ │ Action 2: 写稿 │ │ 输入:Topic │ │ 输入:Research │ │ 输出:Research │ │ 输出:Draft │ └─────────┬─────────┘ └─────────┬─────────┘ ↓ ↓ └────────────────┬────────────────┘ ↓ ┌─────────────────────────────────────────────────────┐ │ 状态更新 → 重新规划 → 下一步 │ │ (每一步执行完都重新评估,动态调整路径) │ └─────────────────────────────────────────────────────┘

2.2 为什么说这才是生产级的思路

我最看重Embabel的一点是:这个规划过程完全不调大模型,就是一段确定性代码在跑。

这意味着什么?

特性大模型驱动的规划Embabel确定性规划
可复现性同样的输入,两次结果可能不一样同样的输入,路径永远一样
可审计性为什么选这一步?答不上来每一步为什么执行,日志写得明明白白
成本规划过程烧token规划不花一分钱token
调试难度玄学,靠prompt工程跟调试普通Java代码一样
出问题追责「模型幻觉了」能精确到哪一步逻辑有问题

我之前用Python框架搭过demo,跑得确实漂亮。但你要问我敢不敢直接放生产环境?心里真有点发怵。原因不复杂——大部分框架是让大模型自己决定下一步干什么,模型今天这么走,明天那么走,出了问题没法复盘。审计问你这一步为什么执行,你总不能说「大模型觉得该这么干」吧?

Rod Johnson盯上的,就是这条缝。大模型负责不确定的那部分(写文案、做总结、搞分类),规划和流程交给确定性的代码。这个分工一摆出来,Java程序员二十年在工程化上攒的东西——类型、测试、审计、监控——突然全都用上了。

2.3 Java程序员最爱的强类型

还有一点特别对Java程序员的胃口:强类型

在Python的Agent框架里,Action之间传的基本上是字典和字符串。你传了个什么进去、期望得到什么出来,全靠文档和约定。改个字段名,你得全局搜索慢慢找,漏了一个就是线上bug。

Embabel不一样。Action之间传的不是字典,是真正的领域对象——Java Record或者Kotlin data class。输入什么类型,输出什么类型,编译期就给你卡住。改个字段名,IDE能把受影响的Action全找出来,一键重构。

// 定义领域对象(Java Record,编译期类型安全) public record Topic(String title, String category) {} public record Research(String summary, List<String> references) {} public record BlogDraft(String content, String title) {} public record Review(List<String> suggestions, int score) {} // 定义Action —— 输入输出都是强类型 @Action(description = "根据主题调研并写出初稿") public BlogDraft writeDraft(Topic topic) { // 调模型写稿 return aiService.generateDraft(topic); } @Action(description = "审校初稿并给出修改意见") public Review reviewDraft(BlogDraft draft) { // 调模型审校 return aiService.review(draft); }

对比一下Python版本的感觉:

# Python 框架里常见的写法 —— 字典传参,全靠约定 def write_draft(state: dict) -> dict: topic = state.get("topic") # 有没有这个key?运行时才知道 content = llm.generate(topic) return {"draft": content} # 下游能不能取到?全靠文档

我之前写Python Agent,重构基本靠全局搜索+人肉检查,对比太强烈了。对于有几十万行业务代码的企业来说,类型安全不是「好不好用」的问题,是「敢不敢上生产」的问题。


三、上手体验:Spring开发者的舒适区

3.1 跟Spring AI的关系:Servlet API和Spring MVC的区别

Rod Johnson自己打过一个比方,我觉得挺准的:

Spring AI 相当于 Servlet API—— 管的是怎么接模型、怎么调向量库这些底层的事Embabel 相当于 Spring MVC—— 是在上面组织业务逻辑、编排Agent的那一层

这个比喻太到位了。你直接用Spring AI也能写Agent,就像你直接用Servlet也能写Web应用一样——不是不能写,是写起来费劲,所有流程都得自己拼。Embabel就是在Spring AI上面给你搭好了MVC那一层。

所以Embabel整个建在Spring AI上面,项目里原来配的模型接入、向量数据库,全都不用动。你原来怎么调大模型,现在还怎么调,Embabel只管编排。

3.2 写一个Agent有多简单

熟悉Spring的人,看一眼代码就懂了:

@Agent(description = "写一个主题的技术博客并审校发布") public class BlogWriterAgent { @Autowired private AiService aiService; @Action(description = "根据主题调研相关资料") public Research doResearch(Topic topic) { return aiService.research(topic); } @Action(description = "根据调研结果写出初稿") public BlogDraft writeDraft(Research research) { return aiService.generateDraft(research); } @Action(description = "审校初稿并给出修改意见") public Review reviewDraft(BlogDraft draft) { return aiService.review(draft); } @Action(description = "根据修改意见润色终稿") public FinalDraft polishDraft(BlogDraft draft, Review review) { return aiService.polish(draft, review); } @Goal public boolean isPublished(FinalDraft draft) { return draft != null && draft.isPublished(); } }

几个关键点:

  • @Agent直接就是个Spring注解,你的类照常走组件扫描和依赖注入
  • 每个Action用@Action标注,描述给规划器看
  • @Goal定义终止条件——什么时候算干完了
  • 先调研还是先写稿、要不要润色、需不需要返工,规划器看着当前状态自己定

你不用写if-else串流程,也不用写prompt让大模型自己想下一步。框架替你把确定性的部分扛了,你只需要专注每个Action具体干什么。

3.3 调用方式也很Spring

@Service public class BlogService { @Autowired private AgentRunner agentRunner; public void publishBlog(String topic) { var goal = new PublishBlogGoal(new Topic(topic, "tech")); var result = agentRunner.run(BlogWriterAgent.class, goal); // result 里有完整的执行轨迹、每一步的输入输出 } }

跟调用一个普通Spring Bean没什么区别。而且因为规划是确定性的,你甚至可以给Agent写单元测试——这在Python框架那边基本是想都不敢想的事。


四、「生产级」这三个字,靠什么支撑

框架上个月刚发正式版,Apache 2.0协议,随便商用,Maven中央仓库直接拉。但真正让我觉得「这玩意儿能上生产」的,是下面这几件事。

4.1 可测试性:Agent也能写单元测试

官方把「Agent可以像Spring Bean一样写单元测试」当成核心卖点,我觉得这才是真正懂企业开发的人会关心的事。

@SpringBootTest class BlogWriterAgentTest { @Autowired private AgentTestRunner testRunner; @Test void should_research_before_writing() { // Mock 掉模型返回 var mockAi = mock(AiService.class); when(mockAi.research(any())).thenReturn(new Research("...", List.of())); when(mockAi.generateDraft(any())).thenReturn(new BlogDraft("...", "...")); // 运行Agent var trace = testRunner.run( BlogWriterAgent.class, new PublishBlogGoal(new Topic("test", "tech")) ); // 断言执行顺序 assertThat(trace.getActions()) .extracting(ActionExecution::getName) .containsExactly("doResearch", "writeDraft", "reviewDraft", "polishDraft"); // 断言发给模型的prompt里有关键词 assertThat(trace.getPromptFor("writeDraft")) .contains("test"); // 甚至能验温度参数设了多少 assertThat(trace.getAction("writeDraft").getTemperature()) .isEqualTo(0.7); } }

给Agent写单测这件事,我在Python那圈框架里基本没见过有人认真做。大部分人的做法是「跑几次看看效果」,然后就祈祷上线别出问题。

4.2 成本控制:每一步都能选不同的模型

Embabel支持每一步动作单独选模型。这个功能看起来不起眼,实际上在生产环境里能省大钱。

任务类型建议模型成本对比
写长文、复杂推理GPT-4o / Claude Opus
分类、提取、摘要GPT-4o Mini / DeepSeek Flash低10-50倍
涉及客户数据的敏感操作本地部署模型(Ollama等)数据不出内网
Embedding本地ONNX模型零成本
@Action(description = "分类用户反馈") @ModelConfig(model = "deepseek-chat", temperature = 0.1) // 便宜的小模型就行 public FeedbackCategory classifyFeedback(String feedback) { return aiService.classify(feedback); } @Action(description = "生成复杂的技术方案") @ModelConfig(model = "claude-opus", temperature = 0.7) // 吃能力的用大模型 public TechnicalSolution generateSolution(Requirements req) { return aiService.generateSolution(req); }

token省了,合规上也好交代。对于企业级应用来说,这不是锦上添花,是刚需。

4.3 生态兼容度:国内团队友好

模型支持方面,除了OpenAI、Anthropic、Google这些国际大厂,DeepSeek、智谱GLM、MiniMax都在支持列表里,Ollama本地部署也直接认。国内团队用起来没什么门槛。

工程化配套也补得挺齐:

  • RAG接口转正—— 不是实验性API,不怕半路改
  • MCP双向支持—— 既能调别人的MCP工具,也能把自己的Agent发布成MCP Server
  • A2A协议—— Agent之间能互相通信、协作
  • Spring Boot Actuator—— 健康状态、指标直接挂上去统一监控
  • ONNX本地Embedding—— 隔离网环境也能用
  • Observability—— 完整的执行轨迹、token用量统计、延迟监控

官方文档里有个数字我印象很深:大约七成的生产应用跑在JVM上。这些公司几十年的业务逻辑全在Java里,做AI的正确姿势是把能力接进现有系统,不是把系统换成Python重写一遍。


五、说几句实话:框架不是完美的

5.1 目前的短板

当然,这框架不是没毛病,我照实说。

方面现状影响
语言核心代码是Kotlin写的Java调用完全无感,但想读源码得适应一下Kotlin语法
Spring Boot版本目前停在Boot 3.5Boot 4还没正式支持,迁移指南已经有了
生态成熟度GitHub Star跟LangChain十万级没法比社区案例少,踩坑可能得自己摸
适用场景适合有Spring体系的企业不在Spring生态里的话,LangChain4j可能更顺手

5.2 谁该关注,谁可以再等等

强烈建议关注的:- 已经在Spring体系里跑了很多年、现在想往业务里塞Agent的团队 - 对可测试性、可审计性、可观测性有硬性要求的企业级应用 - Java/Kotlin为主技术栈、不想为了写Agent特意转Python的团队

可以再等等的:- 纯Python技术栈的团队——LangChain生态更成熟 - 不在Spring体系里的Java项目——LangChain4j可能更轻量 - 需要最前沿的Agent玩法的——新框架功能跟进需要时间


六、我的看法:这可能是Java在AI时代的关键一战

Embabel能不能复制Spring当年的奇迹,我不下结论。Agent这个领域变得太快,框架能不能活到格局稳定那天,谁也说不准。

但Rod Johnson自己有句话我印象很深:

「Embabel可能是最后一波由人类亲自选择的框架——因为以后挑框架、搭技术栈这种事,可能越来越多是AI工具替人做决定。」

这句话有点扎心,但可能是对的。

不过在那一天到来之前,我觉得Embabel的方向是对的:

  1. 确定性和不确定性要分开—— 流程交给代码,创意交给模型
  2. 工程化是底线—— 测试、监控、审计,一个都不能少
  3. 拥抱现有生态—— 不是推翻重来,是给Java程序员递一把新工具

当年Spring把Java从EJB的泥潭里捞出来,这回Rod Johnson想捞的,是我们这些被Python圈在外面的Java程序员。从EJB到Spring,从Servlet到Spring MVC,从JDBC到Spring Data——Rod Johnson好像特别擅长干一件事:在大家都觉得Java不行了的时候,用一个更优雅的方案告诉所有人:不是Java不行,是之前的方案太烂。

反正我Star先点了。值不值得跟,看后续。但作为一个写了十几年Java的老程序员,看到有人还在为JVM生态认真做事,心里挺暖的。


写在最后

Java会不会死?这个问题争论了十几年。我的答案一直是:只要还有人在给Java生态创造好东西,它就死不了。

从Spring到Spring Boot,从Hibernate到MyBatis,从Dubbo到Spring Cloud——每一次「Java不行了」的唱衰背后,都有新的框架、新的思路在冒出来。Embabel会不会成为AI时代的Spring?我不知道。但有人在尝试,这件事本身就很有价值。

你觉得Embabel能成吗?欢迎在评论区聊聊你的看法。



参考资料:本文基于「Java知音」公众号文章《Rod Johnson又来给Java续命了!》整理与扩展,技术解读为作者独立观点。

Embabel开源地址:https://github.com/embabel/embabel-agent


📚 延伸阅读 · 我的付费专栏

觉得这篇文章对你有帮助?我把同类主题的系统化内容沉淀成了付费专栏,欢迎订阅支持持续输出:

专栏定价内容
大模型工程师修炼手记9.9 元51 篇 AI 编程 / Agent 深度实战
AI时代程序员的自我提升89.9 元27 篇 AI 时代成长方法论

💡 一杯咖啡的价格,换来系统化的知识体系;你的订阅,是我持续创作的最大动力。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询