Я очень новичок в Byte Buddy, и я пытаюсь использовать его для создания реализаций интерфейса, который выполняет методы getter для объектов.Мой интерфейс выглядит следующим образом:
public interface Executor {
Object execute(final Object target);
}
И идея в том, что если у меня есть такой класс, как:
public class User {
...
public String getName() { return this.name; }
public String getSurname() { return this.surname; }
}
, мне нужно иметь возможность создать одну реализацию Executor
интерфейс, который execute(obj)
метод предполагает, что obj
является User
и вызывает его getName()
, затем другая реализация, которая делает то же самое для getSurname()
и т. д. Эквивалентный код Java, следовательно, будет:
public class MyHypotheticalByteBuddyExecutorImpl implements Executor {
@Override
Object execute(final Object target) {
return ((User) target).getName();
}
}
Таким образом, идея состоит в том, чтобы иметь возможность создавать классы, подобные описанным выше, для любой комбинации класс + геттер, как в этом случае User
+ getName()
.
Я (думаю, я) знаю, какЗаставьте Byte Buddy создать класс, который почти делает это:
final Method nameMethod = User.class.getMethod("getName", null);
final Class<?> myHypotheticalByteBuddyExecutorImpl =
new ByteBuddy()
.subclass(Object.class)
.implement(Executor.class)
.method(ElementMatchers.named("execute"))
.intercept(MethodCall.invoke(nameMethod).onArgument(0))
.make()
.load(ByteBuddyTest.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
... но затем Byte Buddy справедливо создает исключение, говоря, что я не могу выполнить метод getName()
для Object
.Поэтому я предполагаю, что мне не хватает ((User) target)
приведения:
Exception in thread "main" java.lang.IllegalStateException: Cannot invoke public java.lang.String com.example.User.getName() on class java.lang.Object
at net.bytebuddy.implementation.MethodCall$TargetHandler$ForMethodParameter$Resolved.toStackManipulation(MethodCall.java:2527)
at net.bytebuddy.implementation.MethodCall$Appender.toStackManipulation(MethodCall.java:3541)
at net.bytebuddy.implementation.MethodCall$Appender.apply(MethodCall.java:3502)
...
Я считаю, что это можно определить как StackManipulation
(я могу быть совершенно неправ), что-то вроде:
final StackManipulation typeCasting =
TypeCasting.to(TypeDescription.ForLoadedType.of(User.class));
Но я не могу найти где-нибудь в API-интерфейсе Byte Buddy, как я могу применить это приведение (или любой другой код, который мне может понадобиться для приведения) к аргументу метода execute(Object)
перед выполнением метода получения.
Как я могу это реализовать?