Bytebuddy:是否可以通过将执行替换为 lambda 表达式来拦截方法?

问题描述

是否可以通过将执行替换为 lambda 表达式或其他类的非静态方法拦截方法

例 1:

installByteBuddyAgent();

byteBuddy
        .redefine(sourceClass) //This is important,i need to change a class deFinition
        .method(named(methodName))
        .intercept({{expression}})
        .make()
        .load(
                sourceClass.getClassLoader(),ClassReloadingStrategy.fromInstalledAgent());

//expression = Lambda expression that would be executed in place of the original method,or call a (non-static) method from some other class.

这样做的目的是避免编写一个带有静态方法的类来执行拦截

例 2:

    public class A {
        public void sayHello() {
            System.out.println("Hello");
        }
    }

    public class B {
        public void sayGoodbye() {
            System.out.println("Goodbye");
        }
    }
    
// ...

    @Test
    void interceptAReplacingByB() {
        final Class<A> sourceClass = A.class;
        final B b = Mockito.spy(new B());
        
        byteBuddy
                .redefine(sourceClass)
                .method(named("sayHello"))
                .intercept( /*call sayGoodbye from B or create a lambda expression to do it*/ )
                .make()
                .load(
                        sourceClass.getClassLoader(),ClassReloadingStrategy.fromInstalledAgent());
        
        new A().sayHello();
        
        Mockito.verify(b).sayGoodbye();
    }

代码片段并不代表完整的场景。它只是为了举例说明问题而构建的。

可以通过其他方式拦截公共方法,但目的不是只适用于公共方法,也不是只适用于测试场景。

解决方法

如果我对你的理解正确:

// ...
.intercept(net.bytebuddy.implementation.MethodCall.invoke("sayGoodbye").on(b))
// ...

注意 a static field will be defined in your reimplementation of A to hold the instance of b