使用 ElementMatchers 调用 super class 中已在 ByteBuddy 中覆盖的方法
Invoking a method in super class that has been overriden in ByteBuddy using ElementMatchers
我想在bytebuddy中动态创建class这样的es
public class Parent {
public boolean testMethod(int n){
return true;
}
}
public class Child extends Parent{
@Override
public boolean testMethod(int n) {
return false;
}
public boolean testMethodSuperWrapper(int n){
return super.testMethod(n);
}
}
我写的代码是这样的:
Class parentClass = new ByteBuddy().subclass(Object.class).name("Parent")
.defineMethod("testMethod", boolean.class, Modifier.PUBLIC)
.withParameter(int.class).intercept(FixedValue.value(true))
.make().load(Test.class.getClassLoader()).getLoaded();
Class childClass = new ByteBuddy().subclass(parentClass).name("Child")
.defineMethod("testMethod", boolean.class, Modifier.PUBLIC)
.withParameter(int.class).intercept(FixedValue.value(false))
.defineMethod("testMethodSuperWrapper", boolean.class, Modifier.PUBLIC)
.withParameters(int.class).intercept(MethodCall.invoke(
ElementMatchers.isMethod()
.and(ElementMatchers.hasMethodName("testMethod"))
.and(ElementMatchers.takesArguments(int.class))
//.and(ElementMatchers.isDeclaredBy(parentClass))
)
.onSuper()
.withAllArguments())
.make().load(parentClass.getClassLoader()).getLoaded();
Object childClassObject = childClass.newInstance();
Method superWrapperMethod = childClass.getMethod("testMethodSuperWrapper", int.class);
boolean res = (boolean) superWrapperMethod.invoke(childClassObject, 23);
System.out.println(res);
我知道我可以使用 Method
class 来使 testMethodSuperWrapper
调用父方法但是由于我项目中的原因(循环类型)我需要创建 testMethodSuperWrapper
使用 ElementMatchers 在父 class 中调用 testMethod
。
问题是当我使用 ElementMatchers 调用父 class 中的方法时,就像在我的代码中一样,我收到此错误:Cannot invoke public boolean Child.testMethod(int) as super method of class Child
.
此外,如果我注释 .onSuper()
行并取消注释 .and(ElementMatchers.isDeclaredBy(parentClass))
我会得到这个错误 class Child does not define exactly one virtual method or constructor for (isMethod() and name(equals(testMethod)) and hasParameter(hasTypes(erasures(containing(is(int))))) and declaredBy(erasure(is(class Parent)))) but contained 0 candidates: []
这与 Byte Buddy 的内部模型有关,您可以在其中替换超类型定义的方法,而不是覆盖它。在 Java 中这确实是一样的,但在 Byte Buddy 中,(不幸的是)不是这样。
您可以通过匹配方法来覆盖它,而不是像这样定义它:
new ByteBuddy().subclass(parentClass).name("Child")
.method(ElementMatchers.named("testMethod"))
.intercept(FixedValue.value(false))
这样,您的覆盖就会起作用。
我想在bytebuddy中动态创建class这样的es
public class Parent {
public boolean testMethod(int n){
return true;
}
}
public class Child extends Parent{
@Override
public boolean testMethod(int n) {
return false;
}
public boolean testMethodSuperWrapper(int n){
return super.testMethod(n);
}
}
我写的代码是这样的:
Class parentClass = new ByteBuddy().subclass(Object.class).name("Parent")
.defineMethod("testMethod", boolean.class, Modifier.PUBLIC)
.withParameter(int.class).intercept(FixedValue.value(true))
.make().load(Test.class.getClassLoader()).getLoaded();
Class childClass = new ByteBuddy().subclass(parentClass).name("Child")
.defineMethod("testMethod", boolean.class, Modifier.PUBLIC)
.withParameter(int.class).intercept(FixedValue.value(false))
.defineMethod("testMethodSuperWrapper", boolean.class, Modifier.PUBLIC)
.withParameters(int.class).intercept(MethodCall.invoke(
ElementMatchers.isMethod()
.and(ElementMatchers.hasMethodName("testMethod"))
.and(ElementMatchers.takesArguments(int.class))
//.and(ElementMatchers.isDeclaredBy(parentClass))
)
.onSuper()
.withAllArguments())
.make().load(parentClass.getClassLoader()).getLoaded();
Object childClassObject = childClass.newInstance();
Method superWrapperMethod = childClass.getMethod("testMethodSuperWrapper", int.class);
boolean res = (boolean) superWrapperMethod.invoke(childClassObject, 23);
System.out.println(res);
我知道我可以使用 Method
class 来使 testMethodSuperWrapper
调用父方法但是由于我项目中的原因(循环类型)我需要创建 testMethodSuperWrapper
使用 ElementMatchers 在父 class 中调用 testMethod
。
问题是当我使用 ElementMatchers 调用父 class 中的方法时,就像在我的代码中一样,我收到此错误:Cannot invoke public boolean Child.testMethod(int) as super method of class Child
.
此外,如果我注释 .onSuper()
行并取消注释 .and(ElementMatchers.isDeclaredBy(parentClass))
我会得到这个错误 class Child does not define exactly one virtual method or constructor for (isMethod() and name(equals(testMethod)) and hasParameter(hasTypes(erasures(containing(is(int))))) and declaredBy(erasure(is(class Parent)))) but contained 0 candidates: []
这与 Byte Buddy 的内部模型有关,您可以在其中替换超类型定义的方法,而不是覆盖它。在 Java 中这确实是一样的,但在 Byte Buddy 中,(不幸的是)不是这样。
您可以通过匹配方法来覆盖它,而不是像这样定义它:
new ByteBuddy().subclass(parentClass).name("Child")
.method(ElementMatchers.named("testMethod"))
.intercept(FixedValue.value(false))
这样,您的覆盖就会起作用。