Advice.withCustomMapping()。bind(...)的目的

问题描述 投票:1回答:1

我正在尝试了解Advice.withCustomMapping().bind(...)的用途和用途,以查看它是否对我的用例有用。

读取Advice.withCustomMapping()的javadoc:

允许配置自定义注释,然后将其绑定到动态计算的恒定值。

这是我要应用此模式的用例:

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实例上下文中继到JettyAdviceServletContextAdvice静态上下文。由于建议方法应该是静态的,因此我无法找到一种将实例状态纳入这些方法的方法(没有有效地构建涉及类实例映射的某种外部中继机制,从而导致AgentRule的所有子类中都有复制粘贴的代码) 。此用例正在应用于涉及a lot of rules的项目,这就是为什么我试图找出执行此操作的最高性能和最简洁的方法。

[当我尝试使用Advice.withCustomMapping().bind(...)这种方法时,我从ByteBuddy收到一个异常说:

java.lang.IllegalStateException: org.eclipse.jetty.servlet.ServletContextHandler() does not define an index 0

Advice.withCustomMapping().bind(...)的目的仅是覆盖方法签名中存在的特定参数吗?我在javadocs中找不到提及此内容,并且在网上查看其他示例,我似乎认为我的用例应该可以工作。

java byte-buddy
1个回答
0
投票

您需要

@Retention(RUNTIME)
public @interface Name { }

否则,Buddy Byte Buddy将看不到您的注释,并退回到默认值,即带有相同索引的参数。

© www.soinside.com 2019 - 2024. All rights reserved.