Я пытаюсь понять цель и использование Advice.withCustomMapping().bind(...)
, чтобы посмотреть, может ли это помочь в моем случае использования.
Чтение javado c для 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
в stati c context из JettyAdvice
и ServletContextAdvice
. Так как методы совета должны быть статичны c, я не могу найти способ получить состояние экземпляра в этих методах (без эффективного построения какого-либо внешнего механизма ретрансляции, включающего карты экземпляров класса <->, что приводит к копированию + вставке кода в все подклассы AgentRule
). Этот вариант использования применяется к проекту, который включает в себя множество правил , поэтому я пытаюсь найти наиболее эффективный и краткий способ сделать это.
Когда я пробую этот подход с Advice.withCustomMapping().bind(...)
, я получаю исключение от ByteBuddy, говорящее:
java.lang.IllegalStateException: org.eclipse.jetty.servlet.ServletContextHandler() does not define an index 0
Является ли целью Advice.withCustomMapping().bind(...)
только переопределение определенных c аргументов, которые существуют в сигнатуре метода? Я не смог найти упоминания об этом в javadocs, и, глядя на другие примеры в Интернете, мне кажется, что мой сценарий использования должен работать.