java - Advice.withCustomMapping().bind(...) 的目的
问题描述
我正在尝试了解 的目的和用途Advice.withCustomMapping().bind(...)
,看看它是否可以帮助我的用例。
阅读javadoc Advice.withCustomMapping()
:
允许配置自定义注释,然后将其绑定到动态计算的常量值。
这是我尝试应用此模式的用例:
public @interface Name {
}
public abstract class AgentRule {
private final String className = getClass().getName();
public final Advice.WithCustomMapping advice() {
return Advice.withCustomMapping().bind(Name.class, className);
}
public static boolean isEnabled(final String className, final String origin) {
...
}
public abstract Iterable<? extends AgentBuilder> buildAgent(AgentBuilder builder) throws Exception;
}
public class ServletContextAgentRule extends AgentRule {
public static boolean filterAdded = false;
@Override
public Iterable<? extends AgentBuilder> buildAgent(final AgentBuilder builder) throws Exception {
return Arrays.asList(builder
.type(named("org.eclipse.jetty.servlet.ServletContextHandler"))
.transform(new Transformer() {
@Override
public Builder<?> transform(final Builder<?> builder, final TypeDescription typeDescription, final ClassLoader classLoader, final JavaModule module) {
return builder.visit(advice().to(JettyAdvice.class).on(isConstructor()));
}})
.type(not(isInterface()).and(hasSuperType(named("javax.servlet.ServletContext"))
// Jetty is handled separately due to the (otherwise) need for tracking state of the ServletContext
.transform(new Transformer() {
@Override
public Builder<?> transform(final Builder<?> builder, final TypeDescription typeDescription, final ClassLoader classLoader, final JavaModule module) {
return builder.visit(advice().to(ServletContextAdvice.class).on(isConstructor()));
}}));
}
public static class JettyAdvice {
@Advice.OnMethodExit
public static void exit(final @Name String className, final @Advice.Origin String origin, final @Advice.This Object thiz) {
if (isEnabled(className, origin))
filterAdded = JettyAgentIntercept.addFilter(thiz);
}
}
public static class ServletContextAdvice {
@Advice.OnMethodExit
public static void exit(final @Name String className, final @Advice.Origin String origin, final @Advice.This Object thiz) {
if (isEnabled(className, origin))
filterAdded = ServletContextAgentIntercept.addFilter(thiz);
}
}
}
实际上,我要做的是将信息从实例上下文传递ServletContextAgentRule
到and的静态上下文。由于建议方法应该是静态的,因此我无法找到将实例状态放入这些方法的方法(没有有效地构建某种涉及类<->实例映射的外部中继机制,从而导致在所有子类中复制+粘贴代码)。这个用例被应用于一个涉及很多规则的项目,这就是为什么我试图找出最高效和最简洁的方法来做到这一点。JettyAdvice
ServletContextAdvice
AgentRule
当我尝试使用这种方法时Advice.withCustomMapping().bind(...)
,我从 ByteBuddy 那里得到一个例外,说:
java.lang.IllegalStateException: org.eclipse.jetty.servlet.ServletContextHandler() does not define an index 0
目的Advice.withCustomMapping().bind(...)
仅仅是覆盖方法签名中存在的特定参数吗?我在 javadocs 中找不到提到这一点,并且在网上查看其他示例,我似乎认为我的用例应该可以工作。
解决方案
你需要
@Retention(RUNTIME)
public @interface Name { }
否则 Byte Buddy 看不到您的注释并回退到默认值,即具有相同索引的参数。
推荐阅读
- css - 反应脚本没有与另一个脚本一起启动服务器
- ios - iOS - CIImage autoAdjustmentFilters 泄漏
- javascript - React Native - 打开原生共享
- node.js - 解析来自 mongoose 对象的数组元素的数据产生未定义而简单的元素值正确返回
- php - 查询 PHP 到 Mysql 数据库
- spring-integration - Spring Cloud Stream:如何重新发布到死信队列并抛出异常
- javascript - 随机单词组合javascript
- jquery - 如何获取由 JQuery.data() 创建的具有特定数据属性的元素?
- jenkins - 来自 Jenkins Job 的 Groovy 脚本将数据填充为来自 oracle DB 的组合框需要大量时间
- amazon-web-services - 如何将 S3 存储桶的访问权限限制为特定 VPC,同时允许控制台访问