@Trace 注解不会被 SkyWalking Agent 自动增强,因其仅为语义标记而非增强指令;Agent 仅通过预定义插件增强特定框架类,不扫描自定义注解;需配合 Tracer API 手动创建 Span 或借助 Spring AOP 实现半自动埋点。

Java 中 SkyWalking 的 @Trace 注解本身**不会被 Agent 自动识别和增强**,它仅是 SkyWalking SDK 提供的“手动埋点”标记,需配合 Tracer API 显式创建 Span 才能真正上报链路。Agent 的字节码增强(ByteBuddy)默认只处理 SkyWalking 内置插件(如 Spring MVC、Dubbo、OkHttp 等),**不扫描或增强用户自定义注解**。
为什么 @Trace 不会被 Agent 自动增强?
SkyWalking Agent 的插件机制基于“已知目标类 + 方法签名 + 增强逻辑”的预定义规则。它不会:
- 全局扫描所有带
@Trace的方法并自动插入字节码 - 将
@Trace视为“触发增强的元数据”(类似 Spring AOP 的@Aspect) - 在运行时动态生成代理或修改未在插件配置中声明的目标类
换句话说:@Trace 是一个“语义标记”,不是“增强指令”。它的作用是提醒开发者此处需要追踪,但执行追踪仍需主动调用 SDK。
正确结合方式:@Trace + 手动 Tracer API
推荐做法是在标注 @Trace 的方法内,使用 Tracer 创建本地 Span。这是轻量、可控且与 Agent 完全兼容的方式:
立即学习“Java免费学习笔记(深入)”;
- 确保项目已引入
skywalking-agent.jar并正常启动(-javaagent) - 添加 SDK 依赖:
org.apache.skywalking.apm.toolkit:apm-toolkit-trace - 在业务方法中显式使用
Tracer:
@Trace
public void doBusiness() {
// 创建本地 Span(属于当前 TraceContext)
AbstractSpan span = Tracer.createLocalSpan("DoBusiness");
try {
// 你的业务逻辑
Thread.sleep(100);
} catch (Exception e) {
span.error(e); // 标记异常
throw e;
} finally {
span.end(); // 必须调用,否则 Span 不上报
}
}
进阶:自定义 Agent 插件支持 @Trace(需开发插件)
若确实希望“零侵入”地让 Agent 自动增强所有 @Trace 方法,可开发自定义插件:
- 新建模块,继承
ClassEnhancePluginDefine,重写define方法 - 匹配目标类中带有
@Trace注解的方法(使用AnnotationMatch) - 指定前置(
TraceMethodInterceptor.beforeMethod)和后置(afterMethod)拦截器 - 在拦截器中调用
Tracer.createLocalSpan()和span.end() - 将插件 JAR 放入 Agent
plugins/目录,重启应用
⚠️ 注意:该方式需熟悉 SkyWalking 插件开发规范,且每次升级 Agent 版本都需验证兼容性,生产环境慎用。
替代方案:用 Spring AOP + @Trace 实现半自动埋点
若项目使用 Spring,更实用的做法是结合 AOP 统一处理 @Trace:
- 定义切面,拦截所有标注
@Trace的 public 方法 - 在
@Around中创建 Span,捕获异常,统一结束 - 避免每个方法重复写
Tracer模板代码
@Aspect
@Component
public class TraceAspect {
@Around("@annotation(org.apache.skywalking.apm.toolkit.trace.Trace)")
public Object traceMethod(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().toShortString();
AbstractSpan span = Tracer.createLocalSpan("AOP-" + methodName);
try {
return joinPoint.proceed();
} catch (Exception e) {
span.error(e);
throw e;
} finally {
span.end();
}
}
}
这种方式无需改 Agent,复用现有 SDK,又减少了样板代码,适合大多数 Spring Boot 场景。


















