我有一个建议,在建议中调用类似的方法。我们如何确保一次只调用一次建议。现在,因为我在通知中调用的方法与正在检测的方法相同,所以它进入递归调用并导致java.lang.StackOverflowError。
transform(
new AgentBuilder.Transformer.ForAdvice()
.include(JettyHandlerAdvice.class.getClassLoader())
.advice(named("addFilterWithMapping").and(ElementMatchers.takesArgument(0,named("org.eclipse.jetty.servlet.FilterHolder"))),JettyHandlerAdvice.class.getName())
)
建议
@Advice.OnMethodEnter
private static void before(@Advice.AllArguments Object[] args, @Advice.Origin("#m") String methodName, @Advice.This Object thiz) {
FilterHolder filterHolder = ((org.eclipse.jetty.servlet.ServletHandler)thiz).addFilterWithMapping(XYZFilter.class, "/*", EnumSet.of(javax.servlet.DispatcherType.REQUEST));
}
答案 0 :(得分:0)
Byte Buddy是一个代码生成框架,不是面向方面的。想一想将代码复制粘贴到目标位置;如果您将检测硬编码到目标方法中,那么您所看到的堆栈溢出错误将是相同的。
这可以通过添加标志来避免,例如,您可以在进行递归调用之前定义一个设置为true的ThreadLocal<Boolean>
,例如:
if (!threadLocal.get()) {
threadLocal.set(true);
try {
// your code here.
} finally {
threadLocal.set(false);
}
}
这样,您就可以跟踪递归调用。但是你确实需要管理你的州。一种选择是使用Instrumentation
接口将属性的holder类注入bootstrap类加载器。
或者,您可以检查堆栈是否有重复呼叫。这不如显式状态管理那么有效,但从Java 9开始,您可以使用更便宜的堆栈walker API并使其变得平易近人。