You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为类添加静态方法并委托至已有方法?附Agent及Transformer代码

实现通过Byte Buddy为SpringApplication添加静态委托方法

你已经搭好了Java Agent的基础框架,接下来咱们把给org.springframework.boot.SpringApplication添加静态委托方法的功能补全。核心思路是用Byte Buddy的字节码增强能力,新增一个静态run方法,并把它的调用转发到SpringApplication已有的原生run方法上。

完整的SpringApplicationTransformer实现

import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
import net.bytebuddy.implementation.bind.annotation.Origin;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.agent.builder.AgentBuilder;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class SpringApplicationTransformer implements AgentBuilder.Transformer {

    @Override
    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription,
                                           ClassLoader classLoader, java.lang.module.Module module) {
        try {
            // 定义和原生方法签名一致的静态run方法
            builder = builder
                    .defineMethod("run", Object.class, Modifier.PUBLIC | Modifier.STATIC)
                    .withParameter(Class.class, "primarySource")
                    .withParameter(String[].class, "args")
                    .intercept(MethodDelegation.to(SpringApplicationDelegate.class));
            
            return builder;
        } catch (Exception e) {
            throw new RuntimeException("Failed to inject static run method into SpringApplication", e);
        }
    }

    // 委托类:负责把新方法的调用转发到原生run方法
    public static class SpringApplicationDelegate {
        public static Object run(@Origin Method method, @AllArguments Object[] args) throws Exception {
            // 通过反射获取SpringApplication的原生静态run方法
            Method originalRunMethod = Class.forName("org.springframework.boot.SpringApplication")
                    .getMethod("run", Class.class, String[].class);
            // 调用原生方法并返回结果
            return originalRunMethod.invoke(null, args);
        }
    }
}

关键细节解释

  • 定义新静态方法:用defineMethod声明一个public static的run方法,返回值设为Object(兼容原生方法返回的ConfigurableApplicationContext),参数列表和SpringApplication原生的run(Class<?> primarySource, String... args)完全对齐。
  • 方法拦截与转发:通过MethodDelegation.to()把新方法的调用交给委托类处理,这是Byte Buddy实现方法增强的核心方式。
  • 委托类逻辑:
    • @AllArguments Object[] args:自动捕获调用新方法时传入的所有参数
    • 用反射拿到原生的静态run方法,因为原生方法本身是静态的,所以invoke时第一个参数传null
    • 最后把原生方法的执行结果返回,保证新方法和原生方法的行为完全一致

额外注意事项

  1. 依赖准备:确保项目引入了Byte Buddy的核心依赖,比如Maven配置:
<dependency>
    <groupId>net.bytebuddy</groupId>
    <artifactId>byte-buddy</artifactId>
    <version>1.14.11</version> <!-- 建议使用最新稳定版 -->
</dependency>
<dependency>
    <groupId>net.bytebuddy</groupId>
    <artifactId>byte-buddy-agent</artifactId>
    <version>1.14.11</version>
</dependency>
  1. Agent打包配置:把Agent类和Transformer类打包成jar时,需要在MANIFEST.MF中指定Premain入口:
Premain-Class: com.your.package.Agent
Can-Redefine-Classes: true
  1. 调用验证:完成后你就可以像调用原生方法一样使用这个新增的静态方法,效果完全一致:
SpringApplication.run(YourBootApp.class, args);

内容的提问来源于stack exchange,提问作者Dave Syer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:40:20