从 Spring 微服务萃取代码知识:OpenRewrite 实战指南
一、背景
在企业微服务系统中,如果有 150+ 个 Spring / Spring Boot / Spring Cloud 微服务,仅仅把代码丢进向量数据库做 RAG,实际上很难真正解决:
-
某个 Service 有哪些 API?
-
一个 API 最终调用了哪些 Service?
-
哪些服务依赖某个服务?
-
某个数据库表被哪些服务使用?
-
哪个 Kafka Topic 有哪些生产者和消费者?
-
某个 Java 方法被哪些地方调用?
-
修改一个接口会影响哪些服务?
-
一个业务流程到底经过哪些 Controller、Service、Repository?
-
哪些微服务之间存在 Feign 调用?
-
哪些服务使用 Redis?
-
哪些代码属于 Spring Cloud?
-
某个类、方法、接口在哪个 Git Commit 中发生了变化?
如果这些信息完全依赖 LLM 从源代码中"读出来",成本高、速度慢,而且结果不稳定。
因此更合理的方案是:
让 OpenRewrite / AST / Static Analysis 负责产生事实,让 LLM 负责理解事实。
也就是:
┌─────────────────────┐
│ Git Repository │
│ 150+ Microservices │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Code Scanner │
│ │
│ OpenRewrite │
│ Maven / Gradle │
│ Git │
│ SQL Parser │
└──────────┬──────────┘
│
▼
┌───────────────────────────┐
│ Structural Knowledge │
│ │
│ Service │
│ Package │
│ Class │
│ Method │
│ API │
│ Call │
│ Feign │
│ DB │
│ Kafka │
│ Redis │
│ Dependency │
└────────────┬──────────────┘
│
┌─────────────┴─────────────┐
▼ ▼
PostgreSQL / pgvector Neo4j
文档 / RAG Knowledge Graph
│ │
└─────────────┬─────────────┘
▼
LLM / Agent
│
┌─────────────┼─────────────┐
▼ ▼ ▼
架构分析 影响分析 文档生成
业务流程 依赖分析 Code Agent
二、最终要达到什么效果?
最终希望把一个 Spring 微服务:
order-service
转换成机器可以理解的数据:
Service
├── Package
│ ├── Class
│ │ ├── Field
│ │ └── Method
│ │ ├── Annotation
│ │ ├── Method Call
│ │ ├── SQL
│ │ └── API
│ │
│ └── ...
│
├── REST API
│
├── Feign Client
│
├── Database
│
├── Kafka
│
├── Redis
│
└── Dependencies
例如:
POST /orders
│
▼
OrderController.createOrder()
│
▼
OrderService.createOrder()
│
├──────────────► UserClient.getUser()
│ │
│ ▼
│ user-service
│
├──────────────► InventoryClient.reserve()
│ │
│ ▼
│ inventory-service
│
▼
OrderRepository.save()
│
▼
orders table
│
▼
Kafka: order-created
│
├────────────► payment-service
│
└────────────► notification-service
这才是真正可以供 Agent 使用的"代码知识"。
三、第一阶段:准备开发环境
3.1 推荐环境
如果你的代码主要是 Java / Spring,我建议:
| 软件 | 推荐 |
|---|---|
| OS | Windows / Linux |
| JDK | Java 21 |
| Maven | 3.9.x |
| Git | 2.x |
| IDE | IntelliJ IDEA |
| OpenRewrite | 当前稳定版本 |
| PostgreSQL | 16+ |
| pgvector | 最新稳定版 |
| Neo4j | 5.x |
| Python | 3.11+,用于辅助处理 JSON |
| Node.js | 可选 |
| Docker | 推荐用于 PostgreSQL / Neo4j |
OpenRewrite 当前 Recipe 开发环境要求 JDK 21;官方也推荐 IntelliJ IDEA 2024.1+。
四、Windows 环境安装
如果你是在 Windows 上开发,可以使用 PowerShell。
4.1 检查 Java
java -version
应该看到:
java version "21.x.x"
如果没有:
$env:JAVA_HOME
检查 JAVA_HOME。
例如:
C:\Program Files\Java\jdk-21
设置:
setx JAVA_HOME "C:\Program Files\Java\jdk-21"
重新打开 PowerShell。
五、检查 Maven
mvn -version
例如:
Apache Maven 3.9.x
Java version: 21
如果你的项目本身已经使用 Maven Wrapper:
.\mvnw.cmd -version
优先使用项目自己的 Maven Wrapper。
六、检查 Git
git --version
例如:
git version 2.x
七、Linux 环境
Ubuntu 示例:
sudo apt update
sudo apt install -y git curl unzip
安装 JDK:
sudo apt install -y openjdk-21-jdk
检查:
java -version
然后:
mvn -version
八、第一件事:不要直接处理 150 个服务
强烈建议:
先选择一个典型 Spring Boot 微服务做 POC。
例如:
order-service
最好这个服务同时包含:
-
Controller
-
Service
-
Repository
-
Feign
-
Kafka
-
MyBatis/JPA
-
Redis
-
Maven
-
Spring Boot
这样可以一次性验证整个知识模型。
九、建立代码知识扫描项目
不要把 Scanner 放进业务微服务。
单独建立:
code-knowledge-scanner
建议最终目录:
code-knowledge-scanner
│
├── pom.xml
│
├── src
│ ├── main
│ │ └── java
│ │ └── com.company.knowledge
│ │ ├── recipe
│ │ │ ├── ClassScanner.java
│ │ │ ├── MethodScanner.java
│ │ │ ├── AnnotationScanner.java
│ │ │ ├── RestApiScanner.java
│ │ │ ├── FeignScanner.java
│ │ │ ├── MethodCallScanner.java
│ │ │ ├── KafkaScanner.java
│ │ │ └── DatabaseScanner.java
│ │ │
│ │ ├── model
│ │ │ ├── ServiceInfo.java
│ │ │ ├── ClassInfo.java
│ │ │ ├── MethodInfo.java
│ │ │ ├── ApiInfo.java
│ │ │ ├── DependencyInfo.java
│ │ │ └── KnowledgeGraph.java
│ │ │
│ │ └── Main.java
│ │
│ └── test
│
├── rewrite.yml
│
└── output
十、创建项目
最简单的方法:
mkdir code-knowledge-scanner
cd code-knowledge-scanner
使用 Maven:
mvn -B archetype:generate \
-DgroupId=com.company.knowledge \
-DartifactId=code-knowledge-scanner \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.5
OpenRewrite 官方也提供 Recipe Starter,可以直接作为 Recipe 项目的起点。
十一、理解 OpenRewrite 的三个核心概念
真正开始写 Scanner 前,需要理解:
Source Code
│
▼
Parser
│
▼
LST
│
▼
Visitor
│
▼
Recipe
│
▼
Knowledge
其中:
LST
OpenRewrite 使用 Lossless Semantic Tree 保存代码结构。
例如:
@Service
public class OrderService {
public Order createOrder(User user) {
return repository.save(new Order());
}
}
OpenRewrite 可以识别:
ClassDeclaration
├── Annotation
│ └── @Service
│
├── MethodDeclaration
│ ├── name=createOrder
│ ├── parameter=User
│ └── return=Order
│
└── MethodInvocation
└── repository.save()
十二、Visitor
Visitor 是真正遍历代码的地方。
例如:
visitCompilationUnit()
│
├── package
├── imports
├── classes
│ ├── fields
│ └── methods
│
└── comments
OpenRewrite 官方文档明确说明 Visitor 是 Recipe 中执行核心逻辑的地方。
十三、Recipe
Recipe 是一个分析或者转换任务。
例如:
ClassScannerRecipe
MethodScannerRecipe
RestApiScannerRecipe
FeignScannerRecipe
Recipe 调用 Visitor:
Recipe
│
▼
Visitor
│
▼
LST
│
▼
Knowledge
OpenRewrite 官方把 Recipe 定义为一组针对 LST 的搜索或重构操作。
十四、第一个任务:萃取 Class
第一步不要做 API。
只做:
Class
Package
Superclass
Interface
Annotation
Field
Method
目标:
{
"className": "OrderService",
"fullyQualifiedName": "com.company.order.service.OrderService",
"packageName": "com.company.order.service",
"annotations": [
"org.springframework.stereotype.Service"
],
"superClass": null,
"interfaces": [],
"file": "src/main/java/com/company/order/service/OrderService.java"
}
十五、ClassInfo 数据模型
建议统一定义:
{
"id": "class:com.company.order.service.OrderService",
"serviceId": "order-service",
"type": "CLASS",
"name": "OrderService",
"fullyQualifiedName": "com.company.order.service.OrderService",
"packageName": "com.company.order.service",
"filePath": "src/main/java/com/company/order/service/OrderService.java",
"lineStart": 10,
"lineEnd": 120,
"annotations": [
{
"name": "org.springframework.stereotype.Service"
}
],
"interfaces": [],
"superClass": null
}
注意:
不要只保存简单 JSON。
必须保存:
serviceId
repository
branch
commit
filePath
line
hash
scanTime
因为未来需要做增量扫描和版本比较。
十六、第二个任务:Method
然后萃取:
Method
例如:
public Order createOrder(
Long userId,
CreateOrderRequest request)
保存:
{
"id": "method:com.company.order.service.OrderService#createOrder",
"classId": "class:com.company.order.service.OrderService",
"name": "createOrder",
"signature": "createOrder(Long, CreateOrderRequest)",
"returnType": "com.company.order.domain.Order",
"parameters": [
{
"name": "userId",
"type": "java.lang.Long"
},
{
"name": "request",
"type": "com.company.order.dto.CreateOrderRequest"
}
],
"annotations": [],
"visibility": "public"
}
十七、第三个任务:Annotation
这是 Spring 项目非常关键的一步。
至少识别:
@RestController
@Controller
@Service
@Repository
@Component
@Configuration
@Bean
@Autowired
@Resource
@Transactional
@Async
@Scheduled
@Cacheable
@KafkaListener
@FeignClient
还需要识别:
@RequestMapping
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
以及:
@Entity
@Table
@Id
@Column
十八、第四个任务:REST API
例如:
@RestController
@RequestMapping("/orders")
public class OrderController {
@PostMapping
public Order create(@RequestBody CreateOrderRequest request) {
return orderService.create(request);
}
}
转换成:
{
"id": "api:order-service:POST:/orders",
"serviceId": "order-service",
"controllerClass": "com.company.order.controller.OrderController",
"method": "create",
"httpMethod": "POST",
"path": "/orders",
"requestType": "CreateOrderRequest",
"responseType": "Order"
}
十九、REST API 最重要的关系
不要只保存 API。
要建立:
API
│
▼
Controller Method
│
▼
Service Method
│
▼
Repository Method
│
▼
Database
例如:
{
"from": "api:order-service:POST:/orders",
"relation": "CALLS",
"to": "method:OrderController#create"
}
然后:
{
"from": "method:OrderController#create",
"relation": "CALLS",
"to": "method:OrderService#create"
}
二十、第五个任务:Method Call
这是整个系统非常重要的一步。
例如:
public Order createOrder() {
User user = userService.getUser();
inventoryService.reserve();
return orderRepository.save(order);
}
要生成:
[
{
"caller": "OrderService#createOrder",
"callee": "UserService#getUser"
},
{
"caller": "OrderService#createOrder",
"callee": "InventoryService#reserve"
},
{
"caller": "OrderService#createOrder",
"callee": "OrderRepository#save"
}
]
二十一、为什么必须做 Type Attribution?
假设:
logger.info("hello");
单纯字符串扫描只能知道:
logger.info
但是 OpenRewrite Type Attribution 可以进一步判断:
logger
↓
org.slf4j.Logger
↓
info(String)
这对于准确建立 Method Call Graph 非常重要。OpenRewrite 官方文档明确说明 Type Attribution 能够提供类型解析、方法绑定、继承关系等信息。
所以:
不要使用正则表达式作为 Java 方法调用分析的主方案。
正则可以做辅助搜索,但不能作为最终知识来源。
二十二、第六个任务:Feign
Spring Cloud 系统里面非常重要。
例如:
@FeignClient(name = "user-service")
public interface UserClient {
@GetMapping("/users/{id}")
User getUser(@PathVariable Long id);
}
生成:
{
"id": "feign:order-service:UserClient",
"sourceService": "order-service",
"clientClass": "com.company.order.client.UserClient",
"targetService": "user-service",
"methods": [
{
"name": "getUser",
"httpMethod": "GET",
"path": "/users/{id}",
"returnType": "User"
}
]
}
进一步生成:
{
"from": "service:order-service",
"relation": "CALLS",
"to": "service:user-service",
"via": "FEIGN",
"client": "UserClient"
}
这样就可以建立:
order-service
│
│ FEIGN
▼
user-service
二十三、第七个任务:Repository
识别:
@Repository
JpaRepository
CrudRepository
MongoRepository
@Mapper
MyBatis Mapper
例如:
@Repository
public interface OrderRepository
extends JpaRepository<Order, Long> {
}
生成:
{
"id": "repository:OrderRepository",
"className": "OrderRepository",
"type": "JPA",
"entity": "Order",
"baseRepository": "JpaRepository"
}
二十四、第八个任务:MyBatis SQL
例如:
@Select("""
select *
from orders
where user_id = #{userId}
""")
Order findByUserId(Long userId);
不要只保存 SQL。
应该保存:
{
"id": "sql:OrderMapper#findByUserId",
"mapper": "OrderMapper",
"method": "findByUserId",
"operation": "SELECT",
"tables": [
"orders"
],
"columns": [
"user_id"
],
"sql": "select * from orders where user_id = #{userId}"
}
然后建立:
OrderService#createOrder
│
▼
OrderMapper#findByUserId
│
▼
orders
二十五、第九个任务:JPA
如果使用:
@Entity
@Table(name = "orders")
public class Order {
}
生成:
{
"entity": "Order",
"table": "orders",
"schema": null,
"fields": [
{
"name": "id",
"column": "id",
"type": "Long"
},
{
"name": "userId",
"column": "user_id",
"type": "Long"
}
]
}
最终:
Order
│
▼
orders
二十六、第十个任务:Kafka
例如:
@KafkaListener(topics = "order-created")
public void handle(OrderCreatedEvent event) {
}
生成:
{
"id": "kafka-consumer:order-service:OrderConsumer#handle",
"serviceId": "order-service",
"type": "CONSUMER",
"topic": "order-created",
"method": "OrderConsumer#handle"
}
生产:
kafkaTemplate.send("order-created", event);
生成:
{
"serviceId": "order-service",
"type": "PRODUCER",
"topic": "order-created",
"method": "OrderService#createOrder"
}
然后建立:
order-service
│
│ PRODUCES
▼
order-created
│
│ CONSUMES
▼
payment-service
二十七、第十一个任务:Redis
Spring 项目中可以识别:
RedisTemplate
StringRedisTemplate
@Cacheable
@CachePut
@CacheEvict
例如:
@Cacheable(value = "users", key = "#id")
public User getUser(Long id) {
}
生成:
{
"type": "CACHE",
"serviceId": "user-service",
"method": "UserService#getUser",
"cacheName": "users",
"keyExpression": "#id"
}
二十八、第十二个任务:Maven Dependency
读取:
pom.xml
生成:
{
"groupId": "org.springframework.boot",
"artifactId": "spring-boot-starter-web",
"version": "3.x",
"scope": "compile"
}
最终可以得到:
order-service
│
├── spring-boot
├── spring-cloud
├── openfeign
├── kafka
├── redis
└── postgresql
二十九、OpenRewrite 本身如何运行?
如果你只是验证 OpenRewrite 是否正常工作,可以在一个业务项目里配置 Maven Plugin。
官方 Maven Plugin 支持:
mvn rewrite:run
以及:
mvn rewrite:dryRun
run 会实际修改代码,dryRun 不修改代码并生成 diff。
例如:
mvn rewrite:dryRun
然后:
git diff
查看结果。
三十、建议先验证 OpenRewrite
业务项目:
order-service
进入:
cd order-service
运行:
mvn rewrite:discover
这个命令可以发现当前 classpath 上可用的 Recipe。官方 Maven Plugin 提供了该 goal。
然后测试:
mvn rewrite:dryRun
最后:
mvn rewrite:run
但是:
我们的最终目标不是修改代码,而是利用 OpenRewrite 读取代码并生成 Knowledge。
所以生产环境不要把"代码重构 Recipe"和"知识萃取 Recipe"混在一起。
三十一、推荐建立两个项目
最终建议:
openrewrite-code-knowledge
和:
openrewrite-code-migration
分别负责:
code-knowledge
↓
只读分析
和:
code-migration
↓
代码修改
这是非常重要的架构隔离。
三十二、推荐的 Scanner 模块
最终:
code-knowledge-scanner
│
├── parser
│ ├── JavaParser
│ ├── MavenParser
│ └── GradleParser
│
├── scanner
│ ├── ServiceScanner
│ ├── PackageScanner
│ ├── ClassScanner
│ ├── MethodScanner
│ ├── AnnotationScanner
│ ├── ApiScanner
│ ├── MethodCallScanner
│ ├── FeignScanner
│ ├── RepositoryScanner
│ ├── DatabaseScanner
│ ├── KafkaScanner
│ ├── RedisScanner
│ └── DependencyScanner
│
├── model
│
├── graph
│
├── output
│
└── cli
三十三、统一 Knowledge Model
不要让每个 Scanner 自己定义 JSON。
统一模型:
Knowledge
├── Repository
├── Service
├── Package
├── Class
├── Method
├── Field
├── Annotation
├── API
├── Dependency
├── MethodCall
├── Feign
├── Database
├── SQL
├── Kafka
├── Redis
└── Event
三十四、Service 数据格式
{
"id": "service:order-service",
"name": "order-service",
"repository": "git@company/order-service.git",
"branch": "main",
"commit": "8a91c2f",
"language": "JAVA",
"framework": [
"SPRING_BOOT",
"SPRING_CLOUD"
],
"build": "MAVEN",
"version": "1.0.0",
"scanTime": "2026-09-04T10:00:00Z"
}
三十五、Class 数据格式
{
"id": "class:com.company.order.OrderService",
"serviceId": "service:order-service",
"name": "OrderService",
"fullyQualifiedName": "com.company.order.OrderService",
"packageName": "com.company.order",
"filePath": "src/main/java/com/company/order/OrderService.java",
"lineStart": 20,
"lineEnd": 150,
"annotations": [
"org.springframework.stereotype.Service"
]
}
三十六、Method 数据格式
{
"id": "method:com.company.order.OrderService#createOrder",
"classId": "class:com.company.order.OrderService",
"name": "createOrder",
"signature": "createOrder(CreateOrderRequest)",
"returnType": "Order",
"visibility": "public",
"annotations": [
"org.springframework.transaction.annotation.Transactional"
]
}
三十七、API 数据格式
{
"id": "api:order-service:POST:/orders",
"serviceId": "service:order-service",
"httpMethod": "POST",
"path": "/orders",
"controller": "OrderController",
"method": "createOrder",
"requestType": "CreateOrderRequest",
"responseType": "Order"
}
三十八、关系数据格式
这是整个系统最重要的数据。
推荐统一:
{
"source": "method:OrderService#createOrder",
"relation": "CALLS",
"target": "method:UserService#getUser",
"confidence": 1.0
}
例如:
{
"source": "service:order-service",
"relation": "DEPENDS_ON",
"target": "service:user-service",
"via": "FEIGN"
}
Kafka:
{
"source": "service:order-service",
"relation": "PRODUCES",
"target": "kafka:order-created"
}
数据库:
{
"source": "method:OrderMapper#findByUserId",
"relation": "READS",
"target": "table:orders"
}
三十九、为什么一定要保存 Graph?
因为你的系统最终不是简单的:
Document → Vector
而是:
Node + Relation
例如:
┌─────────────┐
│order-service│
└──────┬──────┘
│
┌──────────┼──────────┐
▼ ▼ ▼
user-service inventory payment
│ │ │
▼ ▼ ▼
users inventory payment
这就是 Knowledge Graph。
四十、推荐 PostgreSQL + Neo4j
第一阶段可以:
PostgreSQL
保存全部事实数据。
例如:
services
classes
methods
apis
dependencies
method_calls
databases
kafka_topics
如果以后关系查询复杂,再加入:
Neo4j
例如查询:
order-service 到 payment-service 中间经过了哪些调用?
Graph DB 非常适合。
四十一、PostgreSQL 表设计
services
CREATE TABLE services (
id VARCHAR(200) PRIMARY KEY,
name VARCHAR(200),
repository TEXT,
branch VARCHAR(200),
commit_hash VARCHAR(100),
language VARCHAR(50),
frameworks JSONB,
scan_time TIMESTAMP
);
classes
CREATE TABLE classes (
id VARCHAR(500) PRIMARY KEY,
service_id VARCHAR(200),
name VARCHAR(500),
fqcn VARCHAR(1000),
package_name VARCHAR(1000),
file_path TEXT,
line_start INT,
line_end INT,
annotations JSONB
);
methods
CREATE TABLE methods (
id VARCHAR(1000) PRIMARY KEY,
class_id VARCHAR(500),
name VARCHAR(500),
signature TEXT,
return_type VARCHAR(1000),
parameters JSONB,
annotations JSONB
);
relations
CREATE TABLE relations (
source_id VARCHAR(1000),
relation_type VARCHAR(100),
target_id VARCHAR(1000),
metadata JSONB,
PRIMARY KEY (
source_id,
relation_type,
target_id
)
);
四十二、最终 JSON 文件目录
每个微服务建议生成:
output/
└── order-service/
└── 8a91c2f/
├── service.json
├── packages.json
├── classes.json
├── methods.json
├── fields.json
├── annotations.json
├── apis.json
├── dependencies.json
├── method-calls.json
├── feign.json
├── database.json
├── sql.json
├── kafka.json
├── redis.json
├── relations.json
└── summary.json
这里:
8a91c2f
就是 Git Commit。
这一步非常重要。
四十三、为什么必须绑定 Git Commit?
假设:
2026-08-01
OrderService#createOrder()
调用:
UserService#getUser()
到了:
2026-09-01
可能已经变成:
CustomerService#getCustomer()
如果没有版本:
Agent
不知道哪个关系是当前的。
所以:
Knowledge Version
=
Repository
+
Branch
+
Commit
+
File Hash
四十四、增量扫描
150 个服务如果每次都全量扫描:
150 × 全部 Java 文件
成本没有必要。
使用:
git diff
找到变化文件。
例如:
git diff --name-only HEAD~1 HEAD
得到:
src/main/java/OrderService.java
src/main/java/OrderController.java
只扫描这些文件。
四十五、但是有一个重要问题
如果:
A.java
调用:
B.java
现在 B.java 修改了。
那么:
A.java
可能没有修改,但是:
A → B
的语义可能发生变化。
所以生产级增量分析应该:
Git Diff
│
▼
Changed Files
│
▼
Changed Symbols
│
▼
Affected Callers
│
▼
Recalculate Graph
第一版可以先做:
文件级增量
第二版再做:
Symbol-level incremental analysis
四十六、第一阶段不要做 LLM
这是整个项目最重要的实施原则之一。
第一阶段:
Java
↓
OpenRewrite
↓
JSON
不要:
Java
↓
LLM
↓
JSON
因为你需要首先建立:
Ground Truth
也就是:
事实层
四十七、什么时候加入 LLM?
等:
Class
Method
API
Call
Feign
DB
Kafka
Redis
Dependency
全部结构化之后,再加入 LLM。
例如:
OrderController#create
│
├── OrderService#create
├── UserClient#getUser
├── InventoryClient#reserve
├── OrderRepository#save
└── Kafka order-created
把这些结构化信息交给 LLM:
请分析这个 API 的业务流程。
LLM 才需要回答:
该接口用于创建订单。
主要流程:
1. 查询用户信息
2. 检查库存
3. 创建订单
4. 保存订单
5. 发布 order-created 事件
涉及:
- user-service
- inventory-service
- order database
- Kafka
这时候 LLM 的 Token 消耗会大幅降低。
四十八、最终 Agent 架构
最终可以做成:
Code Knowledge Platform
│
┌──────────────────┼──────────────────┐
▼ ▼ ▼
Static Facts Knowledge Graph Vector
│ │ │
└──────────────────┼──────────────────┘
▼
Agent Layer
│
┌──────────────────┼──────────────────┐
▼ ▼ ▼
Architecture Agent Impact Agent Business Agent
│ │ │
▼ ▼ ▼
架构分析 影响分析 流程分析
四十九、Agent 可以回答什么?
例如:
问题 1
order-service 依赖哪些服务?
直接查询 Graph:
user-service
inventory-service
payment-service
不需要 LLM。
问题 2
POST /orders 会访问哪些数据库?
Graph:
POST /orders
↓
OrderController#create
↓
OrderService#create
↓
OrderRepository#save
↓
orders
问题 3
修改 Order 表会影响哪些服务?
Graph:
orders
│
├── order-service
├── reporting-service
├── payment-service
└── settlement-service
问题 4
解释创建订单业务流程
这时候再调用 LLM。
五十、第一版必须实现哪些 Scanner?
我建议按照下面顺序:
POC-1
Class
Method
Annotation
目标:
Java → JSON
POC-2
增加:
Spring
REST API
Method Call
目标:
Controller
↓
Service
↓
Method
POC-3
增加:
Feign
Maven
Repository
JPA
MyBatis
SQL
目标:
Service → Service
Service → DB
POC-4
增加:
Kafka
Redis
RabbitMQ
目标:
Event Graph
POC-5
增加:
PostgreSQL
Neo4j
目标:
Knowledge Graph
POC-6
增加:
LLM
RAG
Agent
目标:
Software Intelligence Agent
五十一、150+ 微服务生产架构
最终建议:
GitLab / GitHub
│
▼
Repository Manager
│
▼
┌─────────────────┐
│ Scanner Manager │
└────────┬────────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
Scanner 1 Scanner 2 Scanner N
service A service B service N
│ │ │
└────────────┼────────────┘
▼
OpenRewrite Engine
│
▼
Knowledge JSON
│
┌────────────┼────────────┐
▼ ▼ ▼
PostgreSQL Neo4j Object Storage
│ │
└────────────┼────────────┘
▼
Semantic Layer
│
▼
LLM
│
▼
Agent / RAG / MCP
五十二、推荐 CLI
最终不要让用户直接操作 Java 类。
做成:
code-knowledge scan
例如:
code-knowledge scan \
--repo /workspace/order-service \
--output /output/order-service
指定 Commit:
code-knowledge scan \
--repo /workspace/order-service \
--commit 8a91c2f \
--output /output/order-service/8a91c2f
增量:
code-knowledge scan \
--repo /workspace/order-service \
--from HEAD~1 \
--to HEAD
五十三、最终 CLI
建议设计成:
code-knowledge
│
├── scan
├── scan-all
├── diff
├── export
├── import
├── graph
├── search
└── version
例如:
code-knowledge scan-all \
--repos ./repos \
--output ./knowledge
150 个服务全部扫描。
五十四、一个完整执行流程
实际项目建议严格按照下面顺序执行。
Step 1
安装:
JDK 21
Maven
Git
IntelliJ
Docker
Step 2
创建:
code-knowledge-scanner
Step 3
验证 OpenRewrite:
mvn rewrite:discover
Step 4
选择一个:
order-service
Step 5
执行:
ClassScanner
输出:
classes.json
Step 6
执行:
MethodScanner
输出:
methods.json
Step 7
执行:
AnnotationScanner
输出:
annotations.json
Step 8
执行:
RestApiScanner
输出:
apis.json
Step 9
执行:
MethodCallScanner
输出:
method-calls.json
Step 10
执行:
FeignScanner
输出:
feign.json
Step 11
执行:
DatabaseScanner
输出:
database.json
sql.json
Step 12
执行:
KafkaScanner
输出:
kafka.json
Step 13
执行:
RedisScanner
输出:
redis.json
Step 14
合并:
relations.json
形成:
Service
Class
Method
API
DB
Kafka
Service Dependency
Method Call
完整知识图谱。
五十五、第一阶段验收标准
不要以:
"Scanner 可以运行"
作为验收标准。
应该定义:
Class
95%+
Method
95%+
Spring Annotation
95%+
REST API
95%+
Feign
90%+
DB
80%+
Kafka
90%+
五十六、特别需要注意:静态调用图不是运行时调用图
例如:
if (condition) {
serviceA.call();
} else {
serviceB.call();
}
静态分析只能知道:
A → serviceA
A → serviceB
不能确定运行时到底执行哪一个。
所以最好定义:
STATIC
和:
RUNTIME
两个来源。
最终:
Static Call Graph
+
Runtime Trace
↓
Actual Call Graph
未来可以接:
OpenTelemetry
SkyWalking
Jaeger
Zipkin
这样会更准确。
五十七、不要把所有源码直接放进 RAG
这是另一个非常重要的设计原则。
错误:
Java Source
↓
Embedding
↓
Vector DB
推荐:
Java Source
↓
OpenRewrite
↓
Structured Facts
↓
Graph
↓
LLM Summary
↓
RAG
RAG 中保存:
Service Summary
Class Summary
Method Summary
API Summary
Business Flow
Architecture Summary
Database Usage
Dependency Explanation
而不是把所有源码都作为主要知识。
五十八、最终形成四层知识
建议:
Layer 1:Raw Code
原始代码。
Layer 2:Structural Knowledge
OpenRewrite 萃取。
Layer 3:Semantic Knowledge
LLM 解释。
Layer 4:Business Knowledge
业务流程、架构、领域知识。
结构:
Raw Code
↓
AST/LST
↓
Structural Knowledge
↓
Semantic Knowledge
↓
Business Knowledge
五十九、整个项目的核心原则
如果只记住三句话:
第一
不要让 LLM 成为代码解析器。
第二
让 OpenRewrite / AST / Static Analysis 成为代码事实层。
第三
让 LLM 成为代码知识的语义层。
最终:
OpenRewrite
=
What is actually in the code?
LLM
=
What does this code mean?
Agent
=
What should I do with this knowledge?
六十、建议你的实际落地路线
如果这是一个真正的企业项目,我建议不要直接开发完整平台。
按照:
第 1 周
↓
OpenRewrite 环境
↓
Class / Method Scanner
第 2 周
↓
Spring / REST
↓
API Knowledge
第 3 周
↓
Method Call
↓
Feign
↓
Service Dependency
第 4 周
↓
JPA / MyBatis
↓
SQL
↓
Database Lineage
第 5 周
↓
Kafka / Redis
↓
Event Graph
第 6 周
↓
PostgreSQL
↓
Neo4j
第 7 周
↓
5 个微服务
↓
验证跨服务关系
第 8 周
↓
150+ 微服务
↓
Incremental Scan
第 9 周
↓
LLM Semantic Layer
第 10 周
↓
RAG / Agent
六十一、最终项目目录
最终可以形成:
software-intelligence-platform
│
├── scanner
│ ├── openrewrite
│ ├── maven
│ ├── gradle
│ ├── git
│ └── sql
│
├── knowledge-model
│
├── knowledge-store
│ ├── postgres
│ ├── pgvector
│ └── neo4j
│
├── semantic-engine
│ ├── architecture
│ ├── business-flow
│ ├── dependency
│ └── documentation
│
├── agent
│ ├── architecture-agent
│ ├── impact-agent
│ ├── migration-agent
│ ├── code-agent
│ └── documentation-agent
│
└── cli
└── code-knowledge
六十二、下一步最值得实际开发的东西
不要马上开发 20 个 Scanner。
第一版只实现:
1. ClassScanner
2. MethodScanner
3. AnnotationScanner
4. RestApiScanner
5. MethodCallScanner
6. FeignScanner
然后拿你实际的一个 Spring Boot 微服务跑。
最终必须得到:
service.json
classes.json
methods.json
annotations.json
apis.json
method-calls.json
feign.json
relations.json
如果这 8 个文件能正确生成,整个项目就已经完成了最核心的 POC。
然后再扩展:
MyBatis
JPA
SQL
Kafka
Redis
RabbitMQ
OpenAPI
Config
最后再接:
PostgreSQL
Neo4j
Vector DB
LLM
Agent
六十三、参考资料
OpenRewrite 官方文档目前对 Maven Plugin、Recipe、Visitor、LST、Type Attribution 都有完整说明。Maven Plugin 支持 rewrite:run、rewrite:dryRun、rewrite:discover 等命令;Recipe 开发环境目前要求 JDK 21。
推荐重点阅读:
OpenRewrite Maven Plugin Documentation
总结
对于 150+ Spring 微服务,真正值得建设的不是一个简单的"代码 RAG"。
更准确地说,应该建设:
Software Intelligence Platform(软件智能知识平台)
它的核心链路是:
Git
↓
OpenRewrite
↓
AST / LST / Type Attribution
↓
Structural Knowledge
↓
Knowledge Graph
↓
Semantic Knowledge
↓
RAG
↓
Agent
其中最重要的架构原则是:
事实由代码分析工具产生,语义由 LLM 产生,决策由 Agent 产生。
这样才能真正支撑后面的:
代码理解
架构分析
影响分析
微服务治理
数据库迁移
系统现代化
技术债分析
API 分析
业务流程分析
AI Coding
Migration Agent
Architecture Agent
而不是单纯做一个"把代码塞进向量数据库"的 RAG 系统。