MethodDelegation с передачей массива объектов на определенные параметры с помощью ByteBuddy

interface Foo{
    Object foo(Object... args);
}

static class FooAdapter{
    Object foo2(String msg, Integer age) {
        System.out.println(msg+"=>"+age);
        return age;
    }
}

public static void main(String[] args) throws Exception{
    FooAdapter adapter = new FooAdapter();
    Foo foo = new ByteBuddy()
            .subclass(Foo.class)
            .method(ElementMatchers.named("foo"))
            .intercept(MethodDelegation.to(adapter))
            .make()
            .load(ClassLoader.getSystemClassLoader())
            .getLoaded()
            .newInstance();
    foo.foo("hello", 10);
}

Мой код прост, я просто хочу делегировать fooвызов метода интерфейса Foo FooAdaterfoo2методу экземпляра. Но когда я запускаю тест, ByteBuddy, кажется, ничего не делает.

1 ответ

  1. Делегирование успешно, потому что Byte Buddy решает, что Object::equalsэто лучший метод, который может быть привязан к адаптеру. Он не может связать foo2метод, потому что он ожидает два аргумента типа Stringи Integerпока fooтолько объявляет Object[].

    Делегатор, который вы хотите определить:

    Object foo2(@Argument(0) Object[] arguments) {
      System.out.println(arguments[0] + "=>" + arguments[1]);
      return arguments[0];
    }
    

    где аргумент связан правильно. В противном случае может потребоваться MethodCallинструментирование, в котором можно развернуть аргументы массива. В этом случае необходимо использовать динамический ввод, так как нет способа доказать, что fooвызывается со строкой и целым числом.