我嘗試使用下面的代碼重新定義一個類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)',在這我每一個方法被重新定義時間節省類的字節碼? –
是的,這可能是最可靠的方法。 –
是的,的確,我是能夠做到這樣的,它再完美的作品。感謝您的支持,拉斐爾! –