Ошибка в реализации с интерфейсом

Извините за мой английский, у меня проблемы с реализацией.

У меня есть абстрактный класс только с одним методом, который реализует интерфейс

    package br.com.teste;

public abstract class Test implements IDefault
{
    @Override
    public String test1()
    {
        return "Test method Class";
    }
}

У меня есть интерфейс с методом абстрактного класса

package br.com.teste;

public interface IDefault
{
    public String test1();
}

И у меня есть второй интерфейс, который распространяется на первый и имеет еще один метод

package br.com.teste;

public interface ITest extends IDefault
{
    public String test2();
}

истребитель-перехватчик

package br.com.teste.intercept;

import java.lang.reflect.Method;
import java.util.concurrent.Callable;
import net.bytebuddy.dynamic.TargetType;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
import net.bytebuddy.implementation.bind.annotation.Origin;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.implementation.bind.annotation.Super;
import net.bytebuddy.implementation.bind.annotation.SuperCall;


public class ProxyInvocationHandler
{
    @RuntimeType
    public static Object intercept(@SuperCall Callable<?> callable, @Super(proxyType = TargetType.class) Object delegate, @Origin Class<?> clazz, @Origin Method method, @AllArguments Object[] args) throws Exception
    {
        System.out.println(method.getName());
        //
        return null;
    }
}

Код, который я использую

package br.com.teste;

import br.com.teste.intercept.ProxyInvocationHandler;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatchers;


public class Main
{
    @SuppressWarnings("unchecked")
    public static void main(String... args)
    {
        try
        {
            ClassLoader classLoader = Main.class.getClassLoader();
            Class<? extends ITest> proxyType = (Class<? extends ITest>) new ByteBuddy(ClassFileVersion.JAVA_V8).subclass(Test.class).implement(ITest.class).method(ElementMatchers.any()).intercept(MethodDelegation.to(ProxyInvocationHandler.class)).make().load(classLoader).getLoaded();
            ITest test = proxyType.newInstance();
            //
            System.out.println(test.test1());
            System.out.println(test.test2());
            //
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

ошибка

java.lang.IllegalArgumentException: None of [net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$Record@4d8c5c64] allows for delegation from public abstract java.lang.String br.com.teste.ITest.test2()
    at net.bytebuddy.implementation.bind.MethodDelegationBinder$Processor.bind(MethodDelegationBinder.java:827)
    at net.bytebuddy.implementation.MethodDelegation$Appender.apply(MethodDelegation.java:1035)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyCode(TypeWriter.java:614)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:603)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:521)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:4102)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1612)
    at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:174)
    at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:155)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:2560)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:2662)
    at br.com.teste.Main.main(Main.java:18)

4 ответа

Решение

Ваш test2 Метод абстрагируется вниз по иерархии, и его нельзя вызвать с помощью вызова супер-метода. Следовательно @SuperCall аннотация не может быть привязана к экземпляру, где Byte Buddy отклоняет метод в качестве возможного кандидата на связывание. Вы можете установить @SuperCall(nullIfImpossible = true) иметь null привязать к методу или добавить другой метод перехвата с более слабым требованием, которое Byte Buddy считает своим вторым выбором, если ваш метод не может быть привязан.

Приложение корректно, byte-ddudy должен использовать методы, объявленные в абстрактном классе. Методы, которые только в интерфейсе byte-duddy созданы пустыми. Поскольку я перехватываю все выполняемые методы, для этих пробелов генерируется динамический возврат. Я использовал cglib для этого, и это сработало.

Когда я удаляю "@SuperCall" параметр из метода Interceptor, приложение работает

@RuntimeType
public static Object intercept(@Origin Method method, @AllArguments Object[] args, @Super Object delegate) throws Exception
{
    System.out.println(method.getName());
    //
    return null;
}

Твой класс Test только реализует IDefault интерфейс, который обеспечивает метод test1, Это не реализует ITest интерфейс, который объявляет метод test2, Если это реализовано ITest интерфейс, это будет автоматически означать, что он реализовал IDefault также.

По этой причине вы получаете исключение, в котором говорится, что метода нет test2 доступны в созданном вами подклассе Test,

Другие вопросы по тегам