byte-buddy
byte-buddy copied to clipboard
How to access an injected static field in Advice?
Hello @raphw , I want to inject a static field, whose name is dynamically generated, to some classes, and how could I access this dynamic injected field in Advice class?
The code piece is as below:
String delegatorName; // holds a dynamic generated static field name
builder
.defineField(delegatorName, target, Ownership.STATIC, Visibility.PRIVATE)
.initializer(new LoadedTypeInitializer() {
@Override
public void onLoad(Class<?> type) {
try {
Field field = type.getDeclaredField(delegatorName);
field.setAccessible(true);
field.set(null, Class.forName(interceptor, false, null).getConstructor().newInstance());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public boolean isAlive() {
return true;
}
})
.visit(Advice.to(MyAdviceClass.class))
public class MyAdviceClass {
@Advice.OnMethodEnter
public static boolean onEnter() {
// how could I access the injected static field here???
}
}
Seems that I successfully did that by defining a custom attribute for the Advice class and binding that attribute to the dynamic field. Not sure if it's the best way to do that.
builder.defineField(fieldName, TypeDescription.OBJECT, Ownership.STATIC, Visibility.PRIVATE)
.initializer(new StaticFieldInitializer(fieldName, targetClassName))
.visit(Advice.withCustomMapping()
.bind(Delegator.class, new DynamicFieldDescription(typeDescription, fieldName))
.to(MyAdviceClass.class);
static class DynamicFieldDescription extends FieldDescription.InDefinedShape.AbstractBase {
private final TypeDescription declaringType;
private final String fieldName;
DynamicFieldDescription(TypeDescription declaringType, String fieldName) {
this.declaringType = declaringType;
this.fieldName = fieldName;
}
@Override
public TypeDescription getDeclaringType() {
return declaringType;
}
@Override
public TypeDescription.Generic getType() {
return TypeDescription.OBJECT.asGenericType();
}
@Override
public int getModifiers() {
return ACC_PRIVATE | ACC_STATIC;
}
@Override
public String getName() {
return fieldName;
}
@Override
public AnnotationList getDeclaredAnnotations() {
return null;
}
}
public static MyAdviceClass {
@Advice.OnMethodEnter
public static boolean onEnter(final @Delegator Object delegator) {
}
}
There's @Advice.FieldValue
that can already bind a field. Have you tried using that?
@raphw , Thanks for yoru response. I know the FieldValue
annotation. but since the field name in my case is dynamic, how can I use it in the Advice class?
In this case, you would need to register your own OffsetBinding and resolve a field value dynamically. Have a look at the existing offset bindings for an example.
The comment here I think did the right thing. https://github.com/raphw/byte-buddy/issues/1208#issuecomment-1045792392