Spring-Boot-Online-debug
在日常开发里,大家应该都遇到过这种情况:线上出问题,日志信息不够,定位特别慢。传统手段不是要加日志重新发版,就是要远程 debug,但这些方式都不太优雅。SpringBoot 项目里可以搞个“无痕调试注入器”,做到随时加观察点、随时撤销,而且不用动核心业务逻辑。
从注解切面开始
先来个轻量级方案:写一个注解 @DebugPoint,配合 Spring AOP 就能把入参、出参和耗时打出来,基本上满足大部分排查需求。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DebugPoint {
String value() default "";
}
切面代码如下:
@Aspect
@Component
public class DebugAspect {
private static final Logger log = LoggerFactory.getLogger(DebugAspect.class);
@Around("@annotation(debugPoint)")
public Object around(ProceedingJoinPoint pjp, DebugPoint debugPoint) throws Throwable {
String method = pjp.getSignature().toShortString();
log.info("[DEBUG] 方法: {}, 标签: {}, 参数: {}",
method, debugPoint.value(), Arrays.toString(pjp.getArgs()));
long start = System.currentTimeMillis();
Object result = pjp.proceed();
long cost = System.currentTimeMillis() - start;
log.info("[DEBUG] 方法: {}, 耗时: {}ms, 返回: {}", method, cost, result);
return result;
}
}
在业务方法上加注解:
@Service
public class OrderService {
@DebugPoint("订单创建流程")
public String createOrder(String userId, String productId) {
return "order-" + UUID.randomUUID();
}
}
启动应用后,调用 createOrder 就能在日志里看到完整的调试信息,而业务逻辑完全不用改。
再进一步:热插拔 Agent
如果你想做到“不改源码也能打点”,就要上 Java Agent 了。利用 Instrumentation + ByteBuddy,可以在 JVM 里动态修改字节码,实现运行时增强。DebugAgent.java:
public class DebugAgent {
public static void premain(String args, Instrumentation inst) {
new AgentBuilder.Default()
.type(ElementMatchers.nameContains("OrderService"))
.transform((builder, type, cl, module) ->
builder.method(ElementMatchers.any())
.intercept(Advice.to(DebugAdvice.class)))
.installOn(inst);
}
}
DebugAdvice.java:
public class DebugAdvice {
@Advice.OnMethodEnter
public static void onEnter(@Advice.Origin String method,
@Advice.AllArguments Object[] args) {
System.out.println("[Agent-Enter] 方法: " + method + ", 参数: " + Arrays.toString(args));
}
@Advice.OnMethodExit
public static void onExit(@Advice.Origin String method,
@Advice.Return Object result) {
System.out.println("[Agent-Exit] 方法: " + method + ", 返回: " + result);
}
}
打包成 agent.jar 后,用 JVM 参数挂上:-javaagent:/path/to/agent.jar
这时候即使没有 @DebugPoint 注解,OrderService 里的方法也会被增强,日志会自动打印,真正做 到“线上临时加点”。
SpringBoot Demo 骨架
一个最小可运行的 Demo 项目目录大概是这样的:
demo-debug/
├── src/main/java/com/example/debug/
│ ├── DebugPoint.java # 注解
│ ├── DebugAspect.java # AOP切面
│ ├── OrderService.java # 业务服务
│ ├── DemoApplication.java # 启动类
├── agent/
│ ├── DebugAgent.java # Java Agent入口
│ ├── DebugAdvice.java # 增强逻辑