Day 24:Spring Boot Starter - 开发Java Agent Starter

🤖 系列:Java工程师转AI Agent 3个月学习计划

👤 作者:宸丶一 | 28岁Java程序员

🎯 今日目标: 理解Spring Boot Starter原理,开发Java Agent Starter

💬 个人格言: 代码改不改变世界我不知道,但先让我准时下班。


前言

昨天用gRPC让Python Agent调用Java服务,今天要用Spring Boot Starter封装Agent能力!

Spring Boot Starter是Java生态的核心概念之一,理解它对于开发Java Agent至关重要。

这次直接用MiMo Code生成了一个starter,然后自己做代码Review,发现了7个问题。这种"体验工具→发现问题→理解原理"的学习方式,比光看文档有效多了。


学习目标

  1. 理解Spring Boot Starter原理
  2. 用MiMo Code开发Java Agent Starter
  3. 理解Starter在Agent架构中的价值

一、Spring Boot Starter原理

什么是Starter?

Starter = 空壳依赖聚合包 + 自动配置模块
#mermaid-svg-bVsmxUlzagP6apkV{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-bVsmxUlzagP6apkV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bVsmxUlzagP6apkV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bVsmxUlzagP6apkV .error-icon{fill:#552222;}#mermaid-svg-bVsmxUlzagP6apkV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bVsmxUlzagP6apkV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bVsmxUlzagP6apkV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bVsmxUlzagP6apkV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bVsmxUlzagP6apkV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bVsmxUlzagP6apkV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bVsmxUlzagP6apkV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bVsmxUlzagP6apkV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bVsmxUlzagP6apkV .marker.cross{stroke:#333333;}#mermaid-svg-bVsmxUlzagP6apkV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bVsmxUlzagP6apkV p{margin:0;}#mermaid-svg-bVsmxUlzagP6apkV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-bVsmxUlzagP6apkV .cluster-label text{fill:#333;}#mermaid-svg-bVsmxUlzagP6apkV .cluster-label span{color:#333;}#mermaid-svg-bVsmxUlzagP6apkV .cluster-label span p{background-color:transparent;}#mermaid-svg-bVsmxUlzagP6apkV .label text,#mermaid-svg-bVsmxUlzagP6apkV span{fill:#333;color:#333;}#mermaid-svg-bVsmxUlzagP6apkV .node rect,#mermaid-svg-bVsmxUlzagP6apkV .node circle,#mermaid-svg-bVsmxUlzagP6apkV .node ellipse,#mermaid-svg-bVsmxUlzagP6apkV .node polygon,#mermaid-svg-bVsmxUlzagP6apkV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bVsmxUlzagP6apkV .rough-node .label text,#mermaid-svg-bVsmxUlzagP6apkV .node .label text,#mermaid-svg-bVsmxUlzagP6apkV .image-shape .label,#mermaid-svg-bVsmxUlzagP6apkV .icon-shape .label{text-anchor:middle;}#mermaid-svg-bVsmxUlzagP6apkV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-bVsmxUlzagP6apkV .rough-node .label,#mermaid-svg-bVsmxUlzagP6apkV .node .label,#mermaid-svg-bVsmxUlzagP6apkV .image-shape .label,#mermaid-svg-bVsmxUlzagP6apkV .icon-shape .label{text-align:center;}#mermaid-svg-bVsmxUlzagP6apkV .node.clickable{cursor:pointer;}#mermaid-svg-bVsmxUlzagP6apkV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-bVsmxUlzagP6apkV .arrowheadPath{fill:#333333;}#mermaid-svg-bVsmxUlzagP6apkV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-bVsmxUlzagP6apkV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-bVsmxUlzagP6apkV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bVsmxUlzagP6apkV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-bVsmxUlzagP6apkV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bVsmxUlzagP6apkV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-bVsmxUlzagP6apkV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-bVsmxUlzagP6apkV .cluster text{fill:#333;}#mermaid-svg-bVsmxUlzagP6apkV .cluster span{color:#333;}#mermaid-svg-bVsmxUlzagP6apkV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-bVsmxUlzagP6apkV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-bVsmxUlzagP6apkV rect.text{fill:none;stroke-width:0;}#mermaid-svg-bVsmxUlzagP6apkV .icon-shape,#mermaid-svg-bVsmxUlzagP6apkV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bVsmxUlzagP6apkV .icon-shape p,#mermaid-svg-bVsmxUlzagP6apkV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-bVsmxUlzagP6apkV .icon-shape .label rect,#mermaid-svg-bVsmxUlzagP6apkV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bVsmxUlzagP6apkV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-bVsmxUlzagP6apkV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-bVsmxUlzagP6apkV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Starter内部
Starter用户
引入依赖
自动配置
开箱即用
空壳pom.xml
AutoConfiguration
Properties配置

类比Java

复制代码
Spring Boot Starter ≈ Maven Archetype
├── 预定义的依赖
├── 预定义的配置
└── 开箱即用

Starter的标准结构

复制代码
agent-spring-boot/                     # 父模块
├── agent-spring-boot-starter/         # 空壳依赖聚合(pom.xml)
│   └── pom.xml                        # 依赖autoconfigure
├── agent-spring-boot-autoconfigure/   # 自动配置核心
│   └── src/main/java/...              # 所有代码
└── pom.xml                            # 父pom

spring.factories

properties 复制代码
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.agent.AgentAutoConfiguration

二、用MiMo Code生成Starter

生成的项目结构

复制代码
agent-spring-boot-starter/
├── pom.xml
├── src/main/java/com/example/agent/
│   ├── Agent.java                     # Agent核心类
│   ├── AgentApplication.java          # 示例应用
│   ├── AgentAutoConfiguration.java    # 自动配置
│   ├── AgentManager.java              # Agent管理器
│   └── AgentProperties.java           # 配置属性
├── src/main/resources/META-INF/
│   └── spring.factories               # 注册自动配置
└── target/                            # 已编译成功

关键代码

AgentAutoConfiguration
java 复制代码
@Configuration
@ConditionalOnClass(Agent.class)
@EnableConfigurationProperties(AgentProperties.class)
@ConditionalOnProperty(prefix = "agent", name = "enabled", havingValue = "true", matchIfMissing = true)
public class AgentAutoConfiguration {

    @Autowired
    private AgentProperties agentProperties;

    @Bean
    @ConditionalOnMissingBean
    public Agent agent() {
        Agent agent = new Agent();
        agent.setName(agentProperties.getName());
        agent.setType(agentProperties.getType());
        agent.setVersion(agentProperties.getVersion());
        return agent;
    }

    @Bean
    @ConditionalOnMissingBean
    public AgentManager agentManager(Agent agent) {
        return new AgentManager(agent);
    }
}
AgentProperties
java 复制代码
@ConfigurationProperties(prefix = "agent")
public class AgentProperties {
    private boolean enabled = true;
    private String name = "default-agent";
    private String type = "general";
    private String version = "1.0.0";
    private boolean debug = false;
    private int maxConcurrentRequests = 10;
    private long requestTimeout = 30000;
    
    // getters and setters
}

三、代码Review:发现7个问题

生成完代码后,我自己做了一遍Review,发现了7个关键问题:

问题 严重度 修复建议
pom.xml循环依赖(自己依赖自己) ⚠️ 高 删掉那个依赖
Starter应该拆成两个模块 ⚠️ 中 starter + autoconfigure
AgentApplication在starter里 ⚠️ 中 移到单独example模块
Agent类太简单,没有LLM/Tool/Memory ⚠️ 中 后续迭代添加
AgentManager不是真正的多Agent系统 ⚠️ 低 后续迭代添加
缺少LLM配置(apiKey/baseUrl/model) ⚠️ 中 AgentProperties添加
Spring Boot版本过旧(2.7.18) ⚠️ 低 后续升级3.x

问题1:pom.xml循环依赖

xml 复制代码
<!-- 这里有问题!自己依赖自己 -->
<dependency>
    <groupId>com.example</groupId>
    <artifactId>agent-spring-boot-starter</artifactId>
    <version>1.0.0-SNAPSHOT</version>
</dependency>

问题2:Starter应该拆成两个模块

标准的Spring Boot Starter应该有两个模块:

复制代码
agent-spring-boot/                     # 父模块
├── agent-spring-boot-starter/         # 空壳依赖聚合(pom.xml)
│   └── pom.xml                        # 依赖autoconfigure
├── agent-spring-boot-autoconfigure/   # 自动配置核心
│   └── src/main/java/...              # 所有代码
└── pom.xml                            # 父pom

四、今日收获

知识层面

  • 理解了Spring Boot Starter原理
  • 掌握了Starter的标准结构(starter + autoconfigure)
  • 理解了Starter在Agent架构中的价值

技能层面

  • 能用MiMo Code生成Starter代码
  • 能发现代码中的关键问题(循环依赖、模块拆分)
  • 理解了条件注解的使用场景

思维层面

  • 学会了代码Review(发现了7个问题)
  • 理解了"标准结构"的重要性
  • 理解了Starter和实际产品的差距

五、思考题答案

1. Starter的作用?

Starter = 空壳依赖聚合包 + 自动配置模块;依靠AutoConfiguration.imports注册配置类 + 条件注解按需创建Bean,做到引入依赖即可自动装配组件。

2. 为什么需要Starter?

痛点1:原生Spring依赖繁琐 / 痛点2:大量XML/JavaConfig配置 / 痛点3:组件集成标准不统一。

3. 核心组件?

xxx-spring-boot-starter(空壳) → xxx-spring-boot-autoconfigure(核心)

4. 什么场景用?

经常被调用的比如agent工具、内部的mcp实现。

5. Agent架构中的价值?

开箱即用,循环以及复杂任务拆成简单任务执行时可以省去很多麻烦。

6. 如何设计Agent Starter?

大模型、工具、协同、通信、记忆等多方面都要涉及。

7. Starter vs Archetype?

Starter是项目启动才开始加载和配置以及测试,Maven的话是外部的,启动前就会校验。

8. 新认识?

开箱即用,可以把很多东西都做成可配置的,这样就会刚好适配。


六、明日计划

明天继续深入分析多Agent系统实现!


📝 小小腾老师的评分

维度 得分 评价
Starter掌握程度 ⭐⭐⭐⭐ 理解原理,但标准结构还需要深入
代码实践 ⭐⭐⭐⭐ 能用MiMo Code生成,但有问题需要修复
思考题 ⭐⭐⭐⭐ 80分,部分答案可以更完整
代码Review ⭐⭐⭐⭐⭐ 发现了7个关键问题

总分:80分(良好)

老师说:今天用MiMo Code生成了starter,还做了代码Review,发现了关键问题!明天继续加油!