即使被调用一次,方法也会截获两次
问题描述:
在下面的代码片段中,我将调用方法doStuff
一次在Subclass
的实例上。但它被截获两次。即使被调用一次,方法也会截获两次
请注意,doStuff
是在父类SuperClass
中定义的。如果doStuff
在中定义,则拦截逻辑将按预期工作:只有一个拦截。
我是否错误地使用了Byte Buddy?
package com.test;
import static net.bytebuddy.matcher.ElementMatchers.any;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
import java.util.concurrent.Callable;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType.Builder;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.implementation.bind.annotation.SuperCall;
import org.junit.Test;
public class ReproBugTest {
@Test
public void reproBug() {
new AgentBuilder.Default().type(nameStartsWith("com.test"))
.transform(new AgentBuilder.Transformer() {
@Override
public Builder<?> transform(
Builder<?> builder,
TypeDescription td) {
return builder.method(any())
.intercept(
MethodDelegation.to(MethodInterceptor.class));
}
})
.installOn(
ByteBuddyAgent.installOnOpenJDK());
SubClass subClass = new SubClass();
subClass.doStuff();
}
}
class SuperClass {
public void doStuff() {
System.out.println("Doing stuff...");
}
}
class SubClass extends SuperClass {
}
class MethodInterceptor {
@RuntimeType
public static Object intercept(@SuperCall Callable<?> zuper)
throws Exception {
// Intercepted twice, bug?
System.out.println("Intercepted");
Object returnValue = zuper.call();
return returnValue;
}
}
答
您拦截方法调用每一个类型的,即两个Subclass
和SuperClass
。您需要进一步指定拦截器拦截哪些方法。在你的情况下,你只想拦截方法,如果它们是由给定类型声明的。
这很容易实现。而不是builder.method(any())
,你应该拦截builder.method(isDeclaredBy(td))
。这样,只有在拦截类型声明的方法中才拦截该方法。
最后,我可以看到,您的源代码中使用了旧版本的Byte Buddy。版本0.7-rc6运行稳定,具有附加功能并修复了一些错误。 (然而,一些API仍然需要改变。)
这段代码运行在0.7-rc6上,但我仍然可能会使用一些旧的API。哦,顺便说一句,0.7-rc6的在线javadoc似乎打破了:http://bytebuddy.net/javadoc/0.7-rc6/index.html – user3408654
Byte Buddy代理方法'ByteBuddyAgent.installOnOpenJDK()'应该是ByteBuddyAgent.install ),因为它支持J9和任何Java 9兼容平台。感谢提供给javadoc的提示,是一个命名问题。现在已经修复了。 –