如何在构造函数拦截器中初始化对象字段?
我用Byte Buddy创建了一个构造函数,如下面的代码所示。
Class<?> klass = new ByteBuddy()
.subclass(Object.class, ConstructorStrategy.Default.NO_CONSTRUCTORS)
.defineProperty("origin", CoreObject.class, true)
.defineProperty("variableNamedField", Map.class, true)
.defineConstructor(Visibility.PUBLIC)
.withParameters(CoreObject.class)
.intercept(
// Invoke Objects default constructor explicitly
MethodCall.invoke(Object.class.getConstructor())
.andThen(FieldAccessor.ofField("origin").setsArgumentAt(0))
.andThen(FieldAccessor.ofField("variableNamedField").setsValue(new HashMap<>()))
.andThen(MethodDelegation.to(new FillMapInterceptor("variableNamedField")))
//
// I have to fill the map.
// Something like this:
//
// variableNamedField.put("first", new FirstHandler(origin));
// variableNamedField.put("second", new SecondHandler(origin));
//
)
.make()
.load(CoreObject.class.getClassLoader())
.getLoaded();
首先,构造函数将参数保存到私有字段。然后创建集合。然后调用以下拦截器填充该集合。
class FillMapInterceptor {
private final String mapField;
public FillMapInterceptor(String mapField) {
this.mapField = mapField;
}
public void construct(@FieldValue("variableNamedField") Map<String, Handler> map, @FieldValue("origin") CoreObject coreObject){
map.put("first", new FirstHandler(coreObject));
map.put("second", new SecondHandler(coreObject));
}
}
最好在拦截器中实例化字段 variableNamedField ,因为事实是,每次创建新的类实例时,都使用相同的HashMap对象实例化 variableNamedField 字段。但是,我只能通过@FieldValue批注将现有字段传递给拦截器。但似乎我无法在拦截器中为该字段分配新变量。
答案 0 :(得分:0)
最简单的方法是使用Advice
类定义构造函数。咨询类允许您使用稍后内联的模板来定义代码。在这种情况下,您可以使用@Advice.OnMethodExit
在上面的Implementation
之后添加代码,然后包装上面已经创建的代码:
Advice.to(YourAdvice.class).wrap(...)
基本上,您可以在javadoc中找到有关定义建议的所有信息,您可以将上面的代码粘贴粘贴到静态方法中以内联它:
class YourAdvice {
@Advice.OnMethodExit
static void exit(@Advice.FieldValue("variableNamedField")
Map<Object, Object> variableNamedField) {
variableNamedField.put("first", new FirstHandler(origin));
variableNamedField.put("second", new SecondHandler(origin));
}
}