我尝试使用下面的代码重新定义一个类Bar
2种方法:重新定义一个方法覆盖以前的重新定义
private <T> Class<? extends T> replaceMethodInClass(final Class<T> subclass,
final ClassFileLocator classFileLocator, final String methodName) {
final Builder<? extends T> classBuilder =
this.bytebuddy.redefine(subclass, classFileLocator);
return classBuilder
.method(ElementMatchers.named(methodName))
.intercept(MethodDelegation.to(CustomInterceptor.class))
.make()
.load(ByteBuddyReplaceMethodInClassTest.class.getClassLoader(),
ClassReloadingStrategy.fromInstalledAgent())
.getLoaded();
}
其中CustomInterceptor
类如下:
static class CustomInterceptor {
public static String intercept() {
return "Hello!";
}
}
在我测试,我做了以下重新定义Bar#sayHello()
和Bar#sayHelloAgain()
方法:
@Test
public void shouldReplaceTwoMethodsFromClass_instanciateAfterChanges()
throws InstantiationException, IllegalAccessException, Exception {
// given
replaceMethodInClass(Bar.class, ClassFileLocator.ForClassLoader.of(Bar.class.getClassLoader()),
"sayHello");
replaceMethodInClass(Bar.class, ClassFileLocator.ForClassLoader.of(Bar.class.getClassLoader()),
"sayHelloAgain");
// when
final Bar instance = Bar.class.newInstance();
final String hello = instance.sayHello();
final String helloAgain = instance.sayHelloAgain();
// then
assertThat(hello).isEqualTo("Hello!");
assertThat(helloAgain).isEqualTo("Hello!");
}
请注意,我明确地想要逐个替换方法。 因为hello
变量是null
的测试失败(这是通过在Bar
类的Bar#sayHello()
方法返回的值),但helloAgain
变量被设置为Hello!
,如所预期(使用了CustomInterceptor
类)。所以看起来第一个方法重定义在第二个方法时被删除了。
你有什么想法发生了什么,以及如何保持2方法重新定义,而不是丢失第一个?
感谢您的回应,拉斐尔!所以,为了保持以前的变化,我可以使用基于目录(即ClassFileLocator:'新ClassFileLocator.ForFolder(this.classDir)',在这我每一个方法被重新定义时间节省类的字节码? –
是的,这可能是最可靠的方法。 –
是的,的确,我是能够做到这样的,它再完美的作品。感谢您的支持,拉斐尔! –