byte-buddy icon indicating copy to clipboard operation
byte-buddy copied to clipboard

IllegalArgumentException java.lang.IllegalArgumentException: None of [public static java.lang.Object config.Interceptor.intercept

Open WSKGG opened this issue 5 months ago • 3 comments

when i try to intercept all http request,comes error:IllegalArgumentException but seems my method is being found and method prarms is right. i use java 8 version and bytebuddy 1.17.6 version Image starter:

@Slf4j
@SpringBootApplication
@ComponentScan("config")
public class Main {
    public static void main(String[] args) throws Exception {
        Instrumentation instrumentation = ByteBuddyAgent.install();

        new AgentBuilder.Default()
                // 允许重新定义类
                .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
                .with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE)
                .with(AgentBuilder.TypeStrategy.Default.REDEFINE)
                .with(new AgentBuilder.Listener() {
                    @Override
                    public void onDiscovery(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded) {
                        log.debug("🔍 发现类: {}", typeName);
                    }

                    @Override
                    public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader,
                                                 JavaModule module, boolean loaded, DynamicType dynamicType) {
                        log.info("🔨 转换类: {}", typeDescription.getActualName());

                        try {
                            // ⭐ 保存增强后的字节码到文件
                            String fileName = typeDescription.getSimpleName() + "_Enhanced.class";
                            File outputDir = new File("enhanced-classes");
                            if (!outputDir.exists()) {
                                outputDir.mkdirs();
                            }

                            File classFile = new File(outputDir, fileName);
                            dynamicType.saveIn(outputDir);

                            log.info("💾 增强后的字节码已保存到: {}", classFile.getAbsolutePath());

                        } catch (IOException e) {
                            log.error("❌ 保存字节码文件失败", e);
                        }
                    }

                    @Override
                    public void onIgnored(TypeDescription typeDescription, ClassLoader classLoader,
                                          JavaModule module, boolean loaded) {
                        // 忽略的类
                    }

                    @Override
                    public void onError(String typeName, ClassLoader classLoader, JavaModule module,
                                        boolean loaded, Throwable throwable) {
                        log.error("❌ 转换类失败: {}", typeName, throwable);
                    }

                    @Override
                    public void onComplete(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded) {
                        log.debug("✅ 完成转换: {}", typeName);
                    }
                })
               
                .type((ElementMatchers.isAnnotatedWith(RestController.class)
                        .or(ElementMatchers.isAnnotatedWith(Controller.class)))
                                .and(ElementMatchers.not(ElementMatchers.nameStartsWith("org.springframework")))
                                .and(ElementMatchers.not(ElementMatchers.nameStartsWith("org.springframework")))
                )
            
                .transform((builder, type, classLoader, module, protectionDomain) -> {
         
                    return builder
                          
                            .method(ElementMatchers.isAnnotatedWith(RequestMapping.class)
                                    .or(ElementMatchers.isAnnotatedWith(GetMapping.class))
                                    .or(ElementMatchers.isAnnotatedWith(PostMapping.class))
                                    .or(ElementMatchers.isAnnotatedWith(PutMapping.class))
                                    .or(ElementMatchers.isAnnotatedWith(DeleteMapping.class))
                                    .or(ElementMatchers.isAnnotatedWith(PatchMapping.class)))
                            .intercept(MethodDelegation.to(Interceptor.class)
                            );
                })
                .installOn(instrumentation);
        SpringApplication.run(Main.class, args);
    }

interceptor:

public class Interceptor {
    @RuntimeType //将返回值转换成具体的方法返回值类型,加了这个注解 intercept 方法才会被执行
    public static Object intercept(
            // 被拦截的目标对象 (动态生成的目标对象)
            @This Object target,
            // 正在执行的方法Method 对象(目标对象父类的Method)
            @Origin Method method,
            // 正在执行的方法的全部参数
            @AllArguments Object[] arguments,
            // 目标对象的一个代理
            @Super Object delegate,
            // 方法的调用者对象 对原始方法的调用依靠它
            @SuperCall Callable<?> callable) throws Exception {
        //目标方法执行前执行日志记录
        // 目标方法执行前执行日志记录
        System.out.println("准备执行Method=" + method.getName());
        System.out.println("方法参数: " + Arrays.toString(arguments));
        System.out.println("返回类型: " + method.getReturnType().getName());

        // 调用目标方法
        Object result = callable.call();
        //目标方法执行后执行日志记录
        System.out.println("方法执行完成Method=" + method.getName());
        return result;
    }
}

webController:

@RestController
@RequestMapping("/test")
public class SourceWebController {
    public String hello(String name) {
        return null;
    }
    @RequestMapping("RequestMapping")
    public String testRequestMapping() {
        return "helloRequestMapping";
    }
    @GetMapping("GetMapping")
    public String testGetMapping() {
        return "helloGetMapping";
    }
    @PostMapping("PostMapping")
    public void testPostMapping() {
        System.out.println("helloPostMapping");
    }
}

pom: <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> 2.1.2.RELEASE <relativePath/> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> 1.17.6 <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy-agent</artifactId> 1.17.6 <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId>

WSKGG avatar Aug 11 '25 12:08 WSKGG

Might it be that you are intercepting static methods? That would not allow to be bound. You can also remove parameters and add them incrementally to see why it does not work.

raphw avatar Aug 11 '25 18:08 raphw

Might it be that you are intercepting static methods? That would not allow to be bound. You can also remove parameters and add them incrementally to see why it does not work. thank you for your reply! no, intercepted method is not static method, its the webController's method(In my quesion description).I tried to remove parameters like:

    @RuntimeType
    public static Object interceptNoArgs(@Origin Method method,
                                         @SuperCall Callable<?> callable) throws Exception {

        System.out.println("拦截无参方法: " + method.getName());

        long startTime = System.currentTimeMillis();
        Object result = callable.call();
        long endTime = System.currentTimeMillis();

        System.out.println("无参方法执行完成: " + method.getName() +
                ", 耗时: " + (endTime - startTime) + "ms");

        return result;
    }

but it's not working

WSKGG avatar Aug 12 '25 02:08 WSKGG

Does it still throw the exception?

Possibly, you should use Advice for this, if you want to use retransformation. This is more flexible for this purpose, and is a good for around advice.

raphw avatar Aug 12 '25 20:08 raphw