AgentSkillsCN

java-maven-explorer

自上而下地引导用户理解 Java/Maven 项目。通过提问激发用户的思考,生成与项目目录结构相对应的文档体系,并提供源码阅读路线图。当用户希望深入理解、分析或探索一个 Java/Maven/Scala 项目时,可使用此技能。

SKILL.md
--- frontmatter
name: java-maven-explorer
description: 自顶向下地引导用户理解 Java/Maven 项目。通过提问驱动用户思考,生成与项目目录结构映射的文档体系,提供源码阅读 Roadmap。当用户要求理解、分析、探索一个 Java/Maven/Scala 项目时使用。

Java/Maven 项目探索器

交互式引导用户自顶向下地理解 Java/Maven 项目。核心特点:

  • 提问驱动思考:不是单向讲解,而是通过问题引导用户自己建立对项目的认知
  • 目录映射文档:生成的文档结构镜像项目目录,每个模块/包都有对应文档
  • 源码阅读 Roadmap:为用户规划阅读源码的路径,标注每个文件的阅读优先级
  • 用户水平适配:根据用户知识背景调整解释深度

第一阶段:用户画像

在做任何项目分析之前,使用 AskQuestion 工具了解用户:

code
标题:开始之前
问题1:你对 Java/Maven 生态的熟悉程度?
选项:入门 / 熟悉 / 精通

问题2:你和这个项目的关系?
选项:完全陌生 / 大致了解 / 部分了解 / 参与开发

问题3:你想理解这个项目的目的?
选项:学习研究 / 接手维护 / 排查问题 / 二次开发

写入 .project-understanding/user-profile.md。画像决定后续的解释策略:

水平解释策略
入门所有框架概念、设计模式、注解都展开解释;代码先说"做什么"再说"怎么做";补充前置知识
熟悉通用技术一带而过;聚焦"为什么这样设计";只解释项目特有用法
精通跳过通用解释;直奔架构取舍、性能考量;鼓励用户质疑设计
目的侧重点
学习研究设计思路、架构演进、技术选型理由
接手维护怎么改、改哪里、影响范围
排查问题数据流、异常处理链、日志位置
二次开发扩展点、接口设计、插件机制

第二阶段:全局扫描与思考引导

2.1 自动扫描

  1. 读取根 pom.xml:groupId、artifactId、版本、packaging、modules
  2. 扫描目录结构
  3. 检查 README
  4. 识别构建体系和项目类型

2.2 初始化文档目录(核心改动:镜像项目结构)

文档目录必须镜像项目的模块和包结构,而不是按主题扁平组织。

对于一个多模块项目如:

code
my-project/
├── pom.xml
├── core/
│   └── src/main/java/com/example/core/
├── api/
│   └── src/main/java/com/example/api/
└── service/
    └── src/main/java/com/example/service/

生成的文档结构:

code
.project-understanding/
├── README.md                    # 阅读指南(如何使用这些文档)
├── ROADMAP.md                   # 源码阅读路线图(最重要的导航文件)
├── overview.md                  # 项目总览
├── architecture.md              # 架构设计
├── glossary.md                  # 术语表
├── exploration-log.md           # 探索日志
├── user-profile.md              # 用户画像
│
├── core/                        # ← 镜像 core 模块
│   ├── README.md                # core 模块概览
│   ├── com.example.core/        # ← 镜像包结构(用.分隔的目录名)
│   │   ├── _package.md          # 包级别说明
│   │   ├── CoreService.md       # 关键类文档(按需创建)
│   │   └── CoreConfig.md
│   └── resources.md             # 资源文件说明
│
├── api/                         # ← 镜像 api 模块
│   ├── README.md
│   └── com.example.api/
│       ├── _package.md
│       └── ApiController.md
│
└── service/                     # ← 镜像 service 模块
    ├── README.md
    └── com.example.service/
        └── _package.md

命名规则

  • 模块级:{module}/README.md — 模块概览
  • 包级:{module}/{package}/_package.md — 包的职责说明
  • 类级:{module}/{package}/{ClassName}.md — 只为关键类创建,按需生成
  • 资源级:{module}/resources.md — 配置文件和资源说明

不要一次创建所有文件。初始只创建:

  1. README.md(阅读指南)
  2. ROADMAP.md(源码阅读路线图)
  3. overview.md(项目总览)
  4. 每个模块的 {module}/README.md

其余文件在探索到对应部分时再创建。

2.3 源码阅读 Roadmap(ROADMAP.md)

这是最重要的导航文件。为用户规划一条从宏观到微观的阅读路径。

markdown
# 源码阅读路线图

> 本文档为你规划了一条理解此项目的推荐路径。
> 按顺序阅读标注了 ⭐ 的文件,可以最高效地建立对项目的整体认知。
> 每个阶段末尾有"检查点问题",能回答这些问题说明你已理解该阶段。

## 阅读方式说明

| 标记 | 含义 |
|------|------|
| ⭐ 必读 | 理解项目的关键文件,必须仔细阅读 |
| 📖 推荐 | 有助于加深理解,建议阅读 |
| 📋 参考 | 遇到相关问题时查阅即可 |
| 🔗 | 指向对应的理解文档,阅读源码时可对照参考 |

## 阶段 1:项目全貌(预计 15 分钟)

**目标**:了解项目是做什么的、有哪些模块、怎么构建

| 优先级 | 文件 | 关注点 | 理解文档 |
|--------|------|--------|----------|
| ⭐ 必读 | `pom.xml` | modules 列表、properties、dependencyManagement | [overview.md](overview.md) |
| ⭐ 必读 | `README.md` | 项目用途、快速开始 | - |
| 📖 推荐 | `{module}/pom.xml` (逐个) | 各模块的依赖和职责 | [{module}/README.md]({module}/README.md) |

### ✅ 检查点问题
1. 用一句话描述这个项目是做什么的?
2. 项目有几个模块?它们之间的依赖关系是怎样的?
3. 项目使用了哪些核心框架/技术?

---

## 阶段 2:核心模块(预计 30 分钟)

**目标**:理解最核心模块的代码组织和关键类

| 优先级 | 文件 | 关注点 | 理解文档 |
|--------|------|--------|----------|
| ⭐ 必读 | `{core-module}/src/main/java/.../` | 包结构、核心接口定义 | [{module}/README.md] |
| ⭐ 必读 | `{关键类}.java` | 核心业务逻辑 | [{module}/{package}/{Class}.md] |
| 📖 推荐 | `{配置类}.java` | 配置项和默认值 | [{module}/{package}/{Class}.md] |

### ✅ 检查点问题
1. 核心模块的主要职责是什么?它暴露了哪些接口给其他模块?
2. {根据项目具体情况定制的问题}
3. 数据是怎么在模块间流动的?

---

## 阶段 3:关键流程(预计 45 分钟)
{按项目实际情况填充}

## 阶段 4:扩展与高级(按需)
{按项目实际情况填充}

2.4 展示全貌时的思考引导

展示项目总览后,不要直接让用户选方向,先抛出引导性问题:

code
我已经扫描了整个项目,这是一个 {项目类型},包含 {N} 个模块。

在选择深入方向之前,我想先请你思考几个问题(不需要现在能回答,这些问题会在后续探索中逐步解答):

💭 思考题:
1. 看到这 {N} 个模块的名字,你觉得哪些可能是"核心"模块,哪些可能是"辅助"模块?为什么?
2. 从 pom.xml 的 dependencies 来看,你能猜到这个项目大概在做什么类型的事情吗?
3. {根据项目特点定制的思考题}

不需要回答得很准确,这只是帮助你开始建立自己的"心智模型"。
我们后续的探索会验证或修正这些直觉。

然后再提供探索方向选择。


第三阶段:深入探索

探索循环

每条路径遵循:分析 → 思考引导 → 源码对照 → 记录 的循环。

思考引导问题设计原则

在每个探索节点,设计三类问题:

1. 预判题(在看代码之前问):

code
在打开 {ClassName} 之前,根据它的名字和所在的包 {package},
你觉得它可能负责什么?它可能会依赖哪些其他类?

目的:激活用户的主动思考,后续看到代码时会产生"验证"的效果,加深记忆。

2. 对照题(看完代码后问):

code
现在你看到了 {ClassName} 的实现。
- 它实际做的事情和你之前的预判一致吗?有什么出乎意料的地方?
- 你能解释一下 {某个方法} 的参数为什么要这样设计吗?
- 如果让你来实现同样的功能,你会怎么设计?和作者的方案有什么不同?

目的:促进深层理解,不只是"看过了"而是"想过了"。

3. 关联题(探索多个部分后问):

code
我们已经看了 {模块A} 和 {模块B}。
- 它们之间的边界是怎么划分的?你觉得这种划分合理吗?
- 如果要在 {模块A} 中添加一个新功能,你觉得需要改动哪些地方?
- 你能画出(或描述出)从 {入口} 到 {出口} 的完整数据流吗?

目的:建立跨模块的系统认知。

源码对照机制

在文档中始终保持与源码的双向链接:

文档 → 源码(在文档中标注源码位置):

markdown
## OrderService

订单服务的核心类,负责订单的创建、查询和状态流转。

📁 **源码位置**: `service/src/main/java/com/example/service/OrderService.java`

### 关键方法

| 方法 | 行号 | 作用 | 阅读优先级 |
|------|------|------|------------|
| `createOrder()` | L45-L89 | 创建订单的主流程 | ⭐ 必读 |
| `validateOrder()` | L91-L120 | 参数校验和业务规则检查 | 📖 推荐 |
| `notifyListeners()` | L122-L145 | 通知观察者模式的实现 | 📋 参考 |

### createOrder() 详解
<!-- 前置知识: Spring 事务管理 -->

**调用链**(建议对照源码阅读):
1. `L45`: 入参校验 → 调用 `validateOrder()`
2. `L52`: 生成订单号 → 使用 `IdGenerator`(见 [core/IdGenerator.md](../core/com.example.core/IdGenerator.md))
3. `L58-L70`: 持久化 → 通过 `OrderRepository`
4. `L72-L85`: 发布事件 → Spring ApplicationEvent
5. `L87`: 返回结果

> 💡 注意第 L63 行的 `@Transactional` 注解,这确保了订单创建和库存扣减在同一个事务中。

源码 → 文档(在探索时告诉用户对照关系):

code
你现在可以打开 OrderService.java(L45),对照着 service/com.example.service/OrderService.md 中的流程说明来阅读。
文档中标注了每一步对应的行号,你可以跳着看关键部分。

路径 A: 模块结构探索

  1. 分析每个模块的 pom.xml
  2. 识别模块间依赖
  3. 扫描每个模块的包结构
  4. 归纳模块职责

思考引导

code
我列出了所有模块和它们的依赖关系。

💭 思考题(带着这些问题去看模块代码):
1. 为什么 {module-A} 和 {module-B} 是分开的两个模块而不是一个?分开有什么好处?
2. 有没有哪个模块不依赖任何其他模块?为什么它可以独立存在?
3. 如果让你把这些模块分成"必须有的"和"可选的"两类,你会怎么分?

写入各模块的 {module}/README.md

路径 B: 核心流程追踪

  1. 识别入口点(根据项目类型)
  2. 从入口向下追踪调用链
  3. 在每个关键节点暂停引导思考

暂停检查点(每 3 步暂停一次):

code
到这里为止,我们追踪了:{入口} → {中间节点} → {当前位置}

💭 暂停思考:
- 到目前为止的调用链你能复述吗?(试着不看笔记说一遍)
- {当前位置} 接下来最可能调用谁?为什么你这么猜?
- 如果这个流程出了 bug,你觉得最可能出问题的是哪一步?

想好了可以继续,或者对前面的步骤有疑问可以回头看看。

写入 {module}/{package}/_package.md 或具体类的文档。

路径 C: 依赖分析 / 路径 D: 构建配置 / 路径 E: 指定模块

(这些路径同样遵循"预判 → 对照 → 关联"的思考引导模式,不再赘述。)


文档阅读指南(README.md)

.project-understanding/README.md 是用户拿到文档后的入口。必须包含:

markdown
# 项目理解文档

## 这些文档是什么?

这是通过交互式探索生成的项目理解文档。文档结构镜像了项目的实际目录结构,
你可以像浏览项目源码一样浏览这些文档。

## 怎么使用这些文档?

### 方式 1:按路线图阅读(推荐新手)
打开 [ROADMAP.md](ROADMAP.md),按照标注的阅读顺序,对照源码逐步阅读。
每个阶段末尾有检查点问题,能回答说明你已理解该阶段。

### 方式 2:按模块浏览
进入你感兴趣的模块目录,每个模块的 `README.md` 提供了该模块的概览。
包级别的 `_package.md` 说明了包的职责,类级别的 `{ClassName}.md` 提供了关键类的详细分析。

### 方式 3:搜索特定概念
查看 [glossary.md](glossary.md) 找到术语定义,
或者直接在文档目录中搜索你想了解的类名或概念。

## 文档结构
{自动生成的文档目录树}

## 文档状态标记
| 标记 | 含义 |
|------|------|
| `[确认]` | 通过代码验证的事实 |
| `[推断]` | 基于命名/结构推断,尚未验证 |
| `[待验证]` | 需要进一步确认 |
| `[待探索]` | 尚未深入分析的部分 |

## 源码对照说明
文档中标注了源码文件路径和行号,格式为:
- `📁 源码位置: path/to/File.java` — 文件级别
- `L45-L89` — 行号级别(建议用 IDE 打开源文件对照阅读)

ROADMAP 更新规则

ROADMAP.md 是一个活文档,随探索推进持续更新:

  1. 初始生成:全局扫描后生成骨架,标注阶段 1 的具体文件
  2. 渐进补充:每深入一个模块/流程,在 ROADMAP 中补充该部分的推荐阅读文件和检查点问题
  3. 标注进度:用户已探索的部分标为 ✅ 已探索
  4. 动态调整优先级:如果探索中发现某个文件比预期更重要,提升其优先级
markdown
## 阶段 2:核心模块(预计 30 分钟)

✅ 已探索 | ⭐ 必读 | `core/src/.../CoreService.java` | 核心服务接口 | [core/README.md](core/README.md)
🔲 待探索 | ⭐ 必读 | `core/src/.../CoreConfig.java` | 配置管理 | -
🔲 待探索 | 📖 推荐 | `core/src/.../util/Helper.java` | 工具方法 | -

持续探索循环

每次探索结束后:

  1. 更新对应位置的文档:模块文档放模块目录、包文档放包目录、类文档放类文件
  2. 更新 ROADMAP.md:标注进度、补充新发现的重要文件
  3. 更新 exploration-log.md:记录本轮探索的问答和发现
  4. 动态调整用户画像:如果发现用户水平与初始评估不符

探索日志格式

markdown
## {日期} - {探索主题}

### 用户的思考
{记录用户对思考题的回答要点,这反映了用户对项目的当前理解}

### 关键发现
- {发现1}
- {发现2}

### 源码关键点
| 文件 | 行号 | 说明 |
|------|------|------|
| `path/to/File.java` | L45 | {为什么这行重要} |

### 为用户补充的知识
{本轮额外解释了哪些前置知识}

### 用户理解的变化
{用户之前以为 XXX,现在知道了 YYY}

下一步引导

不要只列选项,要结合探索成果给出有思考方向的引导:

code
我们现在已经了解了 {已探索内容}。

你在刚才的探索中提到 {用户的某个回答/疑问},这和 {未探索的部分} 密切相关。

💭 带着这个新问题想一想:
- {关联性思考题}

建议下一步:
1. {方向1}(可以回答你刚才关于 XXX 的疑问)
2. {方向2}(和你提到的 YYY 有关)
3. 或者你现在有什么新的问题?

设计决策分析(核心能力)

理解一个项目不是知道"它是什么",而是知道"它为什么是这样"。每次分析代码时,必须挖掘设计意图并引导用户理解。

分析方法论:五个"为什么"

对于每一个值得分析的设计点,从五个角度去推理:

1. 问题驱动:它在解决什么问题? 先找到设计存在的理由。不是"这里有一个工厂模式",而是"因为需要根据不同的输入类型创建不同的处理器,所以用了工厂模式"。

推理线索:

  • 看方法签名:参数从哪来、返回值给谁用 → 推断它在流程中的位置
  • 看调用方:谁在调用这段代码 → 推断它解决了调用方的什么需求
  • 看注释和 commit history(如有)→ 直接获取作者意图

2. 替代方案:不这么做会怎样? 每个设计选择都意味着放弃了其他方案。让用户看到选择空间:

code
这里作者选择了 {方案A},而不是:
- 方案B:{描述} — 不选它可能是因为 {推理}
- 方案C:{描述} — 不选它可能是因为 {推理}

推理线索:

  • 这个类/方法解决的问题,业界通常怎么做?
  • 这个项目的约束条件是什么?(性能、兼容性、团队规模、历史包袱)
  • 有没有 TODO/FIXME/HACK 注释暗示了妥协?

3. 约束条件:什么限制了设计空间? 好的设计不是"最优解"而是"约束条件下的最优解"。找出约束:

约束类型线索例子
框架约束继承了框架的基类或实现了框架接口"必须实现 SparkExtension 接口所以结构是这样"
兼容性约束版本号、exclusion、shade"需要同时支持 Spark 2.x 和 3.x 所以用了适配层"
性能约束缓存、池化、批量处理"这里用了对象池而不是每次 new 是因为高频调用"
历史约束废弃的 API、兼容逻辑"保留了旧接口是为了向后兼容"
团队约束统一的代码风格、模块划分方式"所有配置都集中管理是团队约定"

4. 权衡取舍:它得到了什么、放弃了什么? 所有设计都是 trade-off。明确指出:

code
📊 设计权衡:
得到了:{好处1}、{好处2}
放弃了:{代价1}、{代价2}
适合场景:{什么情况下这个选择是合理的}

5. 演进视角:它是一步到位的还是逐步演化的? 推理线索:

  • 有没有多层抽象看起来有些过度?→ 可能是为未来扩展预留的
  • 有没有看起来冗余的代码?→ 可能是历史演进留下的
  • 接口设计是否比当前实现更通用?→ 可能计划支持更多场景

在文档中记录设计决策

每个模块/类文档中,添加 ## 设计决策 段落:

markdown
## 设计决策

### 决策1:{用一个问题描述决策点}
**例:为什么配置管理不用 Spring @ConfigurationProperties 而是自己实现?**

- **选择**: 自实现配置类,通过 buildConf() 注册配置项
- **原因**: [推断] 该项目需要在非 Spring 环境中运行(如嵌入到其他框架时),不能依赖 Spring 容器
- **替代方案**: Spring @ConfigurationProperties — 更方便但引入了 Spring 强依赖
- **权衡**: 得到了框架无关性,代价是需要手动管理配置注册
- **源码依据**: `ConfigManager.java:L23-L45`

### 决策2:{另一个决策点}
...

引导用户思考设计

不要直接给出设计分析结论,而是先引导用户思考:

Step 1 — 抛出设计疑问

code
我注意到这个项目的 {某个特点}。

💭 想一想:
- 如果让你设计这个功能,你的第一直觉是怎么做?
- 为什么作者没有用 {更常见的方案}?你能想到什么原因?

Step 2 — 用户回答后,展示分析

code
你的想法很有道理。实际上作者选择 {方案} 可能是因为:
{展示上面五个维度的分析}

你提到的 {用户的方案} 也是一个合理的选择,在 {某种条件下} 它可能更好。
但在这个项目中,因为 {约束条件},所以 {作者的方案} 更合适。

Step 3 — 开放讨论

code
你觉得这个设计有什么可以改进的地方吗?
如果项目需求发生 {某种变化},这个设计还 hold 得住吗?

在不同层级应用设计分析

层级典型设计问题分析重点
项目级为什么分这些模块?为什么选这个框架?架构权衡、技术选型理由
模块级模块的边界为什么这么划?对外接口为什么这样设计?职责划分、依赖方向
包级包内的类为什么这样组织?哪些是公共 API 哪些是内部实现?封装边界、内聚性
类级为什么用继承/组合/委托?为什么抽象出这个接口?设计模式选择、扩展性考量
方法级参数为什么这样设计?异常为什么这样处理?接口契约、防御性编程

"你可能会好奇"机制

对于反直觉或不明显的设计,主动标注:

code
> 💡 你可能会好奇:这里为什么要把 {X} 和 {Y} 分开成两个类?
> 看起来它们做的事情很相关,放在一起不是更简单吗?
> 
> 分开的原因是 {分析}。如果合并,会导致 {问题}。
> 你可以对比看看 {X} 的调用方(`FileA.java:L30`)和 {Y} 的调用方(`FileB.java:L55`),
> 它们的使用场景确实不同。

上下文感知解释

永远不要假设用户知道某个上下文。遇到以下情况必须主动解释:

  1. 项目内部约定:自定义注解、命名规范、内部 DSL、配置键名
  2. 隐式依赖:SPI、反射加载、auto-configuration、隐式转换
  3. 框架约定:Convention over Configuration 的部分
  4. 跨文件隐含关系:接口在 A 定义、B 实现、C 调用
  5. 设计决策背景:为什么这样做而不是更常见的做法(见"设计决策分析"章节)

解释层次(按用户水平展开到不同深度):

code
第1层:这是什么(一句话定义)
第2层:在项目中扮演什么角色(上下文定位)
第3层:怎么工作的(机制原理)
第4层:为什么这样设计(设计决策分析 — 用上面的五个维度)
第5层:还可以怎么做(替代方案对比 — 帮助用户建立更完整的知识体系)
  • 入门用户:1→2→3,按需到4(用类比解释设计理由)
  • 熟悉用户:1→2→4→5(聚焦设计决策和替代方案)
  • 精通用户:1→4→5(直奔设计权衡,鼓励讨论和质疑)

术语表(glossary.md)

markdown
# 术语表

| 术语 | 含义 | 通俗解释 | 首次出现 | 相关源码 |
|------|------|----------|----------|----------|
| {term} | {精确定义} | {大白话} | {文件路径} | `path/to/File.java:L10` |

文档更新规则

  1. 增量更新:每次只更新有新发现的部分
  2. 确定性标注[确认] / [推断] / [待验证] / [待探索]
  3. 源码关联:每段分析都标注对应的源码位置和行号
  4. 前置知识标注<!-- 前置知识: Maven 生命周期, Spring AOP -->
  5. 文档间链接:使用相对路径互相引用

特殊场景

多语言混合项目(Scala / Kotlin / Groovy)

  • 先判断用户是否熟悉该语言,不熟悉则解释与 Java 的差异
  • 文档目录同样镜像 src/main/scala/ 等目录

Spring Boot 项目

  • 扫描 application.yml / application.properties
  • 追踪 auto-configuration 和 Bean 注册

多模块项目

  • ROADMAP 按模块依赖顺序规划阅读路径(先读被依赖的模块)

快速命令

命令效果
"总结一下"展示当前所有文档概要
"更新文档"将当前理解写入文档
"探索 {模块}"跳到指定模块(自动补全上下文)
"追踪 {类/方法}"从指定位置开始流程追踪
"这个我不懂"对最近内容做更详细解释
"跳过解释" / "详细一点"临时调整解释深度
"看路线图"展示 ROADMAP 和当前进度
"出个题考考我"基于已探索内容生成检查问题
"我觉得 XXX"记录用户的理解,验证正确性

探索质量原则

  1. 问比讲重要:多问引导性问题,少做单向输出
  2. 源码为锚:所有结论都关联到具体的源码位置
  3. 先广后深:先建立全局认知,再选择性深入
  4. 实时记录:边探索边写文档,不要积压
  5. 验证理解:定期通过检查点问题确认用户真正理解了
  6. 关联思维:新发现主动关联已知内容,更新 ROADMAP 和相关文档
  7. 承认不确定:推断性结论必须标注