使用 Byte Buddy 编写 Java Agent:方法拦截与增强实战

洲行

关注

阅读 10

06-13 06:00

当然可以!下面是一个使用 Byte Buddy 实现 Java Agent 的完整示例,演示如何在不修改原始类代码的情况下,动态地拦截并增强一个方法的行为

我们将实现一个简单的 Java Agent,它会在目标方法执行前后打印日志 —— 类似 AOP 的功能。

使用 Byte Buddy 编写 Java Agent:方法拦截与增强实战

项目结构(Maven)

byte-buddy-agent/
├── src/
│   └── main/
│       ├── java/
│       │   ├── MyAgent.java        <-- Java Agent 入口
│       │   └── HelloTransformer.java <-- ClassFileTransformer
│       └── resources/
│           └── MANIFEST.MF
└── pom.xml

添加 Maven 依赖(pom.xml

<dependencies>
    <!-- Byte Buddy 核心库 -->
    <dependency>
        <groupId>net.bytebuddy</groupId>
        <artifactId>byte-buddy</artifactId>
        <version>1.14.0</version>
    </dependency>

    <!-- 可选:用于运行测试的目标类 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

编写 Java Agent 主类(MyAgent.java

import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.matcher.ElementMatchers;

import java.lang.instrument.Instrumentation;

public class MyAgent {

    public static void premain(String args, Instrumentation inst) {
        System.out.println("Java Agent 加载成功...");

        new AgentBuilder.Default()
            .type(ElementMatchers.named("com.example.MyService")) // 拦截指定类
            .transform((builder, typeDescription, classLoader, module) ->
                builder.method(ElementMatchers.named("sayHello")) // 拦截 sayHello 方法
                       .intercept(Advice.to(HelloMethodAdvice.class)) // 插入增强逻辑
            ).installOn(inst);
    }
}

定义增强逻辑(HelloMethodAdvice.java

import net.bytebuddy.asm.Advice;

public class HelloMethodAdvice {

    @Advice.OnMethodEnter
    public static void beforeMethod() {
        System.out.println("[Before] 正在调用 sayHello 方法...");
    }

    @Advice.OnMethodExit
    public static void afterMethod() {
        System.out.println("[After] sayHello 方法执行完成。");
    }
}

配置 MANIFEST.MF 文件

resources/MANIFEST.MF 中写入:

Manifest-Version: 1.0
Premain-Class: MyAgent
Can-Redefine-Classes: true
Can-Retransform-Classes: true

打包 Agent JAR

使用 Maven 打包:

mvn clean package

生成的 JAR 包位于:target/byte-buddy-agent-1.0-SNAPSHOT.jar

准备目标类(可选测试用)

创建一个测试类 com.example.MyService

package com.example;

public class MyService {
    public String sayHello() {
        return "Hello from MyService!";
    }

    public static void main(String[] args) {
        MyService service = new MyService();
        System.out.println(service.sayHello());
    }
}

运行测试命令

启动时带上 Agent:

java -javaagent:target/byte-buddy-agent-1.0-SNAPSHOT.jar -cp target/classes com.example.MyService

输出结果:

Java Agent 加载成功...
[Before] 正在调用 sayHello 方法...
Hello from MyService!
[After] sayHello 方法执行完成。


精彩评论(0)

0 0 举报