bytebuddy definefield and initialize a complex object

84 Views Asked by At

I'am developing a dirty-tracker tool, which will track the object's props changed. So I want to use bytebuddy to inject a field: DirtyTracker dirtyTracker, and hook all setXXX() method. Now I don't know how to initialize dirtyTracker by bytebuddy, this's my code:

protected static <T> Class<? extends T> patchPojo(Class<T> clazz) {
        return new ByteBuddy()
                .subclass(clazz)
                .method(ElementMatchers.nameStartsWith("set"))
                .intercept(MethodDelegation.to(PojoInterceptor.class))
                .defineField("dirtyTracker", DirtyTracker.class, Modifier.PUBLIC)
                .make()
                .load(InjectUtils.class.getClassLoader())
                .getLoaded();
}

By the way, I want to initialize dirtyTracker before the constructor function, because we will do somework with setXXX() in the constructor function, like that:

public class Foo {
    // What I want to do is: define a field and assign it. 
    // public DirtyTracker dirtyTracker = new DirtyTracker();

    private int age;

    public Foo() {
        // dirtyTracker must not null
        setAge(18);
        // now dirtyTracker has mark prop:age dirty.
    }
    
    public void setAge(int i) {
        this.age = i;
    }
    public int getAge() {
        return this.age;
    }
}

I have try to intercept construct: constructor(ElementMatchers.any()).intercept(MethodDelegation.to(PojoInterceptor.class).andThen(SuperMethodCall.INSTANCE))

and

constructor(ElementMatchers.any()).intercept(Advice.to(PojoInterceptor.class))

but it seems can't get the pojo instance in intercept function.

1

There are 1 best solutions below

2
On

The only way of doing this would be to set the field within the constructor. You can define a custom constructor with the interceptor as a parameter of the required type, where you would set the field as the first instruction.