# MethodAop **Repository Path**: bzhuang/method-aop ## Basic Information - **Project Name**: MethodAop - **Description**: 方法调用链路 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-07 - **Last Updated**: 2026-02-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Debugger Trace - 方法调用链跟踪组件 ## 1. 项目概述 Debugger Trace是一个轻量级的Spring Boot方法调用链跟踪组件,通过`@Traceable`注解和配置驱动的方式,实现对Spring Boot应用程序方法的拦截和调用链追踪。组件使用AspectJ技术,支持拦截所有类型的方法(包括私有方法),并提供直观的调用链可视化输出。 ### 1.1 核心功能 - **注解驱动拦截**:使用`@Traceable`注解标记需要追踪的方法 - **配置驱动拦截**:通过`application.properties`配置拦截模式,支持通配符 - **全方法支持**:使用AspectJ实现对所有方法(包括私有方法)的拦截 - **调用链可视化**:以树状结构展示方法调用层级关系 - **性能监控**:记录每个方法的执行时间、开始/结束时间戳 - **异常追踪**:捕获并记录方法执行过程中的异常信息 - **多格式输出**:支持控制台打印和JSON文件导出 - **线程安全**:每个线程的调用链独立存储,互不影响 ### 1.2 技术栈 - Spring Boot 2.7.x - Spring AOP - AspectJ(编译时织入) - Lombok - Jackson(JSON处理) ## 2. 核心组件 ### 2.1 TraceNode `TraceNode`类表示调用链路中的一个方法调用节点,包含以下核心属性: | 属性名 | 类型 | 描述 | | ------------------ | --------------- | ------------------------------------ | | `id` | Integer | 节点序号,自动生成 | | `packageName` | String | 方法所在的包名 | | `className` | String | 方法所在的类名 | | `methodName` | String | 方法名 | | `startTime` | long | 方法开始执行时间戳 | | `endTime` | long | 方法结束执行时间戳 | | `duration` | long | 方法执行耗时(毫秒) | | `success` | boolean | 执行状态(true为成功,false为失败) | | `exceptionMessage` | String | 异常信息(如果执行失败) | | `children` | List | 子节点列表,即当前方法调用的其他方法 | 主要方法: - `end()`:结束方法调用,计算执行耗时 - `addChild()`:添加子节点 - `setException()`:记录异常信息 - `print()`:控制台打印节点信息 - `toJson()`:转换为JSON字符串 - `writeToJsonFile()`:写入JSON文件 ### 2.2 TraceContext `TraceContext`类用于管理调用链路上下文,使用`ThreadLocal`存储每个线程的调用链信息,确保线程安全。 主要方法: - `getTraceStack()`:获取当前线程的调用链路栈 - `getRootNode()`:获取当前线程的根节点 - `setRootNode()`:设置当前线程的根节点 - `clear()`:清理当前线程的上下文信息 ### 2.3 PrivateMethodAspect `PrivateMethodAspect`是核心的AOP切面类,合并了原MethodTraceAspect和PrivateMethodAspect的功能,支持拦截所有方法(包括私有方法)。 - **切点**:拦截所有类的所有方法,排除AOP相关类以避免递归 - **环绕通知**:在方法执行前后记录调用信息,构建完整调用链 - **判断逻辑**: - 方法有`@Traceable`注解 - 方法在`method.interceptor.patterns`配置的模式中 - 方法在已追踪的调用链中被调用 ### 2.4 TraceProperties 配置属性类,用于读取`application.properties`中的`method.interceptor.patterns`配置。 ### 2.5 TraceAutoConfiguration Spring Boot自动配置类,确保组件在Spring Boot项目中自动装配。 ## 3. 使用方法 ### 3.1 作为Maven依赖使用 #### 3.1.1 安装到本地Maven仓库 ```bash # 打包并安装到本地Maven仓库 mvn clean install -DskipTests ``` #### 3.1.2 在目标Spring Boot项目中添加依赖 ```xml com.phoenix debugger-trace 1.0.0 ``` #### 3.1.3 配置AspectJ Maven插件 在目标Spring Boot项目的pom.xml中添加AspectJ Maven插件配置,用于实现编译时织入: ```xml org.springframework.boot spring-boot-maven-plugin com.example.demo.DemoApplication -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 org.projectlombok lombok-maven-plugin 1.18.12.0 generate-sources delombok false src/main/java ${project.build.directory}/generated-sources/delombok org.codehaus.mojo aspectj-maven-plugin 1.14.0 ${java.version} true ${java.version} ${java.version} ${project.build.sourceEncoding} true true true warning ${project.build.directory}/generated-sources/delombok **/*.java **/aop/* **/springframework/cglib/* **/springframework/aop/* com.phoenix debugger-trace compile test-compile org.aspectj aspectjtools ${aspectj.version} org.apache.maven.plugins maven-compiler-plugin 3.8.1 ${java.version} ${java.version} ${project.build.sourceEncoding} ``` #### 3.1.4 配置application.properties 在目标项目的`application.properties`文件中添加拦截模式配置: ```properties # 方法拦截配置 # 配置格式:packageName.className.methodName,支持通配符*和** # 多个配置项用逗号分隔 method.interceptor.patterns=com.example.demo.controller.**.*,com.example.demo.service.**.* ``` **配置模式说明:** - `com.example.*.*`:拦截com.example包下所有类的所有方法 - `com.example.**.*`:拦截com.example包及其子包下所有类的所有方法 - `com.example.UserService.*`:拦截UserService类的所有方法 - `com.example.*.get*`:拦截所有类以get开头的方法 #### 3.1.5 使用@Traceable注解 在需要追踪的方法上添加`@Traceable`注解: ```java import com.phoenix.trace.aop.Traceable; @Service public class YourService { @Traceable public void yourMethod() { // 业务逻辑 } } ``` ### 3.2 拦截机制说明 组件的拦截逻辑如下: **方法会被拦截的条件:** 1. **方法有@Traceable注解且匹配配置的拦截模式**,或者 2. **方法在已追踪的调用链中被调用且匹配配置的拦截模式** 这意味着: - 只有同时满足注解和配置模式的方法才会成为调用链的根节点 - 只有匹配配置模式的方法才会被包含在调用链中作为子节点 **配置示例:** ```properties # 拦截 com.example.demo.controller 包及其子包下所有类的所有方法 # 和 com.example.demo.service 包及其子包下所有类的所有方法 method.interceptor.patterns=com.example.demo.controller.**.*,com.example.demo.service.**.* ``` **实际逻辑判断:** ```java // 如果当前方法有@Traceable注解且匹配配置模式,或者在追踪上下文中且匹配配置模式,则进行拦截 if (!((isTraceable && matchesConfigPattern) || (isInTraceContext && matchesConfigPattern))) { return joinPoint.proceed(); // 不满足条件,直接执行目标方法 } ``` **拦截模式匹配规则:** ```java // AspectConfig.java 中的匹配逻辑 private boolean matchesPattern(String str, String pattern) { String regex = pattern .replace("**", "##WILDCARD##") // 先替换 ** 为临时标记 .replace(".", "\\.") // 转义点字符 .replace("*", "[^\\.]*") // 替换单个 * 为匹配非点字符 .replace("##WILDCARD##", ".*"); // 最后替换临时标记为 .* regex = "^" + regex + "$"; // 确保完全匹配 return str.matches(regex); } ``` **配置模式示例:** - `com.example.*.*`:拦截 com.example 包下所有类的所有方法 - `com.example.**.*`:拦截 com.example 包及其子包下所有类的所有方法 - `com.example.UserService.*`:拦截 UserService 类的所有方法 - `com.example.*.get*`:拦截所有类以 get 开头的方法 这种设计确保了只有符合预期的方法会被拦截,避免了不必要的性能开销。 ### 3.3 组件集成测试 #### 3.3.1 模式匹配修复说明 在 `AspectConfig.java` 中修复了通配符模式匹配的顺序问题。原实现中先替换 `*` 再替换 `**`,导致 `**` 匹配不正确。修复后的实现: ```java private boolean matchesPattern(String str, String pattern) { String regex = pattern .replace("**", "##WILDCARD##") // 先替换 ** 为临时标记 .replace(".", "\\.") // 转义点字符 .replace("*", "[^\\.]*") // 替换单个 * .replace("##WILDCARD##", ".*"); // 最后替换临时标记为 .* regex = "^" + regex + "$"; // 确保完全匹配 return str.matches(regex); } ``` #### 3.3.2 与Spring AOP的兼容性测试 组件已测试与Spring AOP的兼容性: 1. **Spring AOP依赖**: ```xml org.springframework.boot spring-boot-starter-aop ``` 2. **避免冲突的配置**: 在使用 AspectJ Maven 插件时,建议排除对 Spring AOP 切面类的处理: ```xml org.codehaus.mojo aspectj-maven-plugin 1.14.0 **/aop/* ``` #### 3.3.3 调试连接方式 启动项目 Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f) Maven home: D:\maven\apache-maven-3.6.3-bin\apache-maven-3.6.3\bin\.. Java version: 17.0.12, vendor: Oracle Corporation, runtime: C:\Program Files\Java\jdk-17 cd d:\ben\METHOD\debugger ; mvn clean install cd "d:\ben\METHOD\demo-project" ; mvn clean compile spring-boot:run 1. 在 IDE(如 IntelliJ IDEA)中打开项目 2. 点击顶部菜单 Run → Edit Configurations 3. 点击 + 号,选择 Remote 类型 4. 配置: - 名称: Debug for Demo Project - 主机: localhost - 端口: 5005 5. 点击 OK 6. 点击调试按钮(绿色虫子图标) ## 4. 输出格式 ### 4.1 控制台输出 调用链结束后,会在控制台打印类似以下格式的信息: ``` === 方法调用链路 === TestController.createOrder - 120ms (SUCCESS) OrderService.createOrder - 100ms (SUCCESS) ProductService.processProductName - 20ms (SUCCESS) ProductService.getProductDetails - 30ms (SUCCESS) ProductService.calculatePrice - 15ms (SUCCESS) ManualService.getManualDetails - 25ms (SUCCESS) =================== 调用链路已写入JSON文件: call_trace_1767715597480.json ``` ### 4.2 JSON文件输出 调用链会以JSON格式保存到项目根目录,文件名为`call_trace_${timestamp}.json`,内容示例: ```json { "id": 1, "packageName": "com.example.debugger.controller", "className": "TestController", "methodName": "createOrder", "startTime": 1767715597480, "endTime": 1767715597600, "duration": 120, "success": true, "children": [ { "id": 2, "packageName": "com.example.debugger.service", "className": "OrderService", "methodName": "createOrder", "startTime": 1767715597485, "endTime": 1767715597585, "duration": 100, "success": true, "children": [ { "id": 3, "packageName": "com.example.debugger.service", "className": "ProductService", "methodName": "processProductName", "startTime": 1767715597525, "endTime": 1767715597545, "duration": 20, "success": true, "children": [] }, // 其他子节点... ] } ] } ``` ## 5. 项目结构 ``` debugger/ ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── phoenix/ │ │ │ └── trace/ │ │ │ ├── Application.java # 应用程序入口 │ │ │ ├── aop/ # AOP相关类 │ │ │ │ ├── Traceable.java # @Traceable注解 │ │ │ │ ├── PrivateMethodAspect.java # 核心切面类 │ │ │ │ ├── TraceContext.java # 上下文管理类 │ │ │ │ ├── TraceNode.java # 调用节点类 │ │ │ │ └── AspectConfig.java # 配置类 │ │ │ ├── autoconfigure/ # 自动配置 │ │ │ │ ├── TraceAutoConfiguration.java # 自动装配类 │ │ │ │ └── TraceProperties.java # 配置属性类 │ │ └── resources/ │ │ ├── META-INF/ │ │ │ └── spring.factories # Spring Boot自动装配配置 ├── pom.xml # Maven配置 ├── README.md # 项目文档 └── .gitignore # Git忽略文件 ``` ## 6. 性能考虑 - **AOP开销**:AOP会带来一定的性能开销,生产环境建议谨慎使用或缩小跟踪范围 - **内存使用**:每个调用链会占用一定内存,大量并发请求时需要注意内存使用情况 - **文件I/O**:JSON文件写入是同步的,可能会影响响应时间,可以考虑异步写入 ## 7. 总结 Debugger Trace是一个功能强大且易用的Spring Boot方法调用链跟踪组件,它通过注解和配置驱动的方式,实现了对应用程序方法的自动拦截和调用链追踪。 ### 7.1 主要优势 1. **零侵入式**:无需修改业务代码,通过注解和配置即可启用 2. **强大的拦截能力**:支持拦截所有类型的方法(包括私有方法) 3. **灵活的配置**:通过`application.properties`配置拦截模式,支持通配符 4. **完整的调用链**:自动追踪方法调用的完整层级关系 5. **直观的可视化**:树状结构输出和JSON文件导出 6. **生产就绪**:轻量级设计,性能开销可控 ### 7.2 适用场景 - **开发调试**:快速定位方法调用问题 - **性能分析**:识别性能瓶颈和慢方法 - **业务理解**:可视化复杂业务流程的执行路径 - **测试验证**:验证方法调用关系是否符合预期 ### 7.3 未来规划 - 支持更多输出格式(XML、HTML、图表) - 提供Web界面查看和分析调用链 - 添加性能指标统计功能 - 支持分布式系统的调用链跟踪(链路追踪) - 优化性能,降低AOP开销 ### 7.4 替代方案:使用 SkyWalking 实现方法调用链追踪 除了使用本组件的 AOP 方式外,还可以使用 **SkyWalking** 来实现方法调用链追踪,包括对私有方法的追踪。SkyWalking 是一个开源的分布式追踪系统,支持跨服务调用链追踪,性能开销低,适合生产环境使用。 #### 7.4.1 SkyWalking 优势 - **支持私有方法追踪**:通过自定义增强规则,可追踪任意访问修饰符的方法 - **跨服务追踪**:支持微服务架构下的跨服务调用链追踪 - **性能开销低**:基于字节码增强,对应用影响小 - **实时监控**:提供 Web UI 实时查看调用链和性能指标 - **生产环境友好**:支持生产环境部署 #### 7.4.2 配置步骤 ##### 步骤 1:下载并安装 SkyWalking 1. 从 [SkyWalking 官网](https://skywalking.apache.org/downloads/) 下载最新版本的 SkyWalking 2. 解压下载的压缩包,得到 `apache-skywalking-apm-bin` 目录 ##### 步骤 2:配置 SkyWalking Agent 1. **复制 Agent 目录**:将 `apache-skywalking-apm-bin/agent` 目录复制到应用服务器 2. **修改 Agent 配置**:编辑 `agent/config/agent.config` 文件,设置服务名和 OAP 服务器地址: ```properties # 服务名(必填) agent.service_name=demo-app # OAP 服务器地址(默认本地) collector.backend_service=localhost:11800 ``` ##### 步骤 3:配置私有方法追踪规则 1. **创建增强规则目录**:在 `agent/config` 目录下创建 `enhancements` 文件夹 2. **创建规则文件**:在 `enhancements` 目录下创建 `private-method-trace.yml` 文件: ```yaml # 增强规则:追踪私有方法 selector: # 选择需要增强的类(支持正则表达式) class: name: match: "com.example.demo.service.*Service" # 匹配所有 Service 类 # 增强行为:追踪方法执行 enhance: # 追踪所有方法(包括私有方法) methods: - name: match: ".*" # 匹配所有方法名 # 记录方法参数和返回值(可选) params: true returnValue: true ``` 3. **启用自定义规则**:在 `agent/config/agent.config` 中添加: ```properties # 启用自定义增强规则 agent.enhancements_dir=config/enhancements ``` ##### 步骤 4:启动 SkyWalking OAP 服务器 ```bash # 进入 SkyWalking 目录 cd apache-skywalking-apm-bin/bin # 启动 OAP 服务器和 UI(Windows 执行 startup.bat) ./startup.sh ``` ##### 步骤 5:启动应用并添加 Agent 启动应用时,通过 `-javaagent` 参数加载 SkyWalking Agent: ```bash java -javaagent:/path/to/skywalking-agent.jar -jar demo-web-0.0.1-SNAPSHOT.jar ``` ##### 步骤 6:查看调用链 1. 打开浏览器访问 `http://localhost:8080`(SkyWalking UI 地址) 2. 在 **"追踪"** 标签页中输入服务名 `demo-app`,点击查询 3. 查看完整的方法调用链,包括私有方法的调用 #### 7.4.3 效果示例 在 SkyWalking UI 中,您会看到类似以下的调用链结构: ``` demo-app └── GET /test/product └── TestController.createProduct (5ms) └── ProductService.createProduct (3ms) └── ProductService.validateProduct (private, 1ms) # 私有方法被追踪 └── ProductMapper.insert (1ms) └── SQL: INSERT INTO product (...) ``` #### 7.4.4 注意事项 - **性能开销**:SkyWalking Agent 会带来一定的性能开销(约 5-10%),生产环境建议根据实际情况调整追踪范围 - **内存使用**:Agent 会占用一定内存,建议为应用分配足够的内存 - **网络带宽**:Agent 会向 OAP 服务器发送追踪数据,需要确保网络带宽充足 - **版本兼容性**:确保 SkyWalking Agent 版本与应用的 Java 版本兼容 SkyWalking 是一个功能强大的分布式追踪系统,不仅可以实现方法调用链追踪,还可以监控服务健康状态、识别性能瓶颈等,是生产环境中实现可观测性的重要工具。