how to intercept a method with specific parameters with bytebuddy

2.4k views Asked by At

I want to intercept method named methodA with one arg which's type is String as blow, what should i do. How to use hasParameters() api?

public class Demo {

    public static void main(String[] args) {

        new ByteBuddy()
                .subclass(A.class)
                .method(named("methodA").and(hasParameters(?)))
    }


    static class A {

        public void methodA() {
            System.out.println("methodA() invoked.");
        }

        public void methodA(String arg) {
            System.out.println("methodA(" + arg + ") invoked.");
        }
    }

}
2

There are 2 answers

1
k5_ On

For this you want the ElementMatchers.takesArguments(String.class) matcher.

So something like that:

    Class<? extends A> loaded =  new ByteBuddy().subclass(A.class)
       .method(ElementMatchers.named("methodA").and(ElementMatchers.takesArguments(String.class)))
       .intercept(MethodDelegation.to(Demo.class))
       .make().load(Demo.class.getClassLoader(), ClassLoadingStrategy.Default.INJECTION).getLoaded();

    A instance = loaded.getConstructor().newInstance();
    instance.methodA("abc");
    instance.methodA();


public class Demo {

    static void intercept(String arg){
         System.out.println("intercepted");
    }
}
0
ryan On

To clarify, you need to define a matcher (similar to a filter) to apply to methods. Create some constraint in the matcher so it will only match to some parameter structure you specify:

ElementMatcher<Iterable<? extends ParameterDescription>> matcher = parameterDescriptions -> {
    for (ParameterDescription p : parameterDescriptions) {
        if (p.getType().equals(TypeDescription.STRING.asGenericType()) && p.getIndex() == 0) return true;
    }
    return false;
};

ByteBuddyAgent.install();
new ByteBuddy()
    .redefine(SomeType.class)
    .method(ElementMatchers.hasParameters(matcher))
    .intercept(FixedValue.value("Hello World"))
    .make()
    .load(SomeType.class.getClassLoader(), 
        ClassReloadingStrategy.fromInstalledAgent());