Невозможно запустить перехватчик ByteBuddy, если указан аргумент @Morph - PullRequest
1 голос
/ 17 июня 2020

Мне нужно создать собственные классы на основе некоторого ввода. У меня есть атм:

    final Class service = ...;
    final Method method = ...;

    final DynamicType.Unloaded unloadedType = new ByteBuddy()
        .subclass(Object.class)
        .name(service.getClass().getSimpleName() + "DynamicResolver")
        .defineMethod(
            endpointName,
            resolveReturnType(method),
            Modifier.PUBLIC)
       .withParameters(parameters)
       .intercept(MethodDelegation
            .withDefaultConfiguration()
            .withBinders(Morph.Binder.install(Morphing.class))
            .to(interceptor).andThen(
                MethodCall.invoke(method).on(service).withArgument(arguments)
            ))
       .make()

Я здесь создаю класс с единственным методом, который делегирует его предоставленному. Однако параметры созданного метода и метода делегата немного отличаются. У созданного метода на один аргумент больше (в parameters). Созданный метод не принимает этот аргумент, следовательно, массив arguments с индексами аргументов (на один аргумент меньше).

Пока все в порядке. Теперь мне нужно добавить дополнительный аргумент при вызове метода делегирования. Для простоты примера представьте, что нам нужно добавить еще одну строку для вызова делегата.

Как я видел из документации, способ управления аргументами использует @Morph. Итак, я сделал:

public interface Morphing<T> {
    T invoke(Object[] args);
}

и мой перехватчик:

public class Interceptor {
    @RuntimeType
    public Object invoke(
        @Morph final Morphing<Integer> m,
        @AllArguments final Object[] args
    ) {
        System.out.println("!!!");
        return m.invoke(args);
    }
}

К сожалению, это не работает. Когда я удаляю аргумент @Morph, вызывается перехватчик.

Что мне здесь не хватает?

EDIT: @Morph используется только для подклассов, а не при делегировании другому экземпляру ?

EDIT2: пример

1 Ответ

1 голос
/ 02 июля 2020

Byte Buddy связывает метод класса Object так, что желаемый перехватчик больше не запускается. Вы можете добавить filter(isDeclaredBy(MyInterceptor.class)) после withDefaultConfiguration(), чтобы избежать этого. При этом вы получите исключение, что Byte Buddy не может связать ни один из ваших методов.

Причина, по которой @Morph делает класс неприменимым, заключается в том, что нет супер-метода для вызова. В вашем примере вы определяете новый метод, который не имеет исходной реализации. Чтобы использовать аннотацию, вам потребуется переопределить существующий метод.

...