Sergey
Sergey

Reputation: 947

How to create a default constructor with ByteBuddy?

I use ByteBuddy and I have this code:

public class A extends B {
    public A(String a) {
        super(a);
    }

    public String getValue() {
        return "HARDCODED VALUE";
    }
}

public abstract class B {
    private final String message;

    protected B(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

My current generation code is:

Constructor<T> declaredConstructor;

try {
    declaredConstructor = A.class.getDeclaredConstructor(String.class);
} catch (NoSuchMethodException e) {
    //fail with exception..
}

new ByteBuddy()
    .subclass(A.class, Default.IMITATE_SUPER_CLASS)
    .name(A.class.getCanonicalName() + "$Generated")
    .defineConstructor(Visibility.PUBLIC)                               
    .intercept(MethodCall.invoke(declaredConstructor).with("message"))                                                                         
    .make()        
    .load(tClass.getClassLoader(),ClassLoadingStrategy.Default.WRAPPER)
    .getLoaded()
    .newInstance();

I want to get instance of class A, and also I want to make some actions in constructor after invoke super(), like this:

public A(){
   super("message");

   // do something special..
}

I tried implement with MethodDelegation.to(DefaultConstructorInterceptor.class), but I didn't succeed.

Upvotes: 2

Views: 770

Answers (1)

Rafael Winterhalter
Rafael Winterhalter

Reputation: 43972

The JVM requires you to hard-code the super method call into a method what is not possible using delegation (also see the javadoc), this is why you cannot use the MethodDelegation to invoke the constructor. What you can do is to chain the method call you already have and the delegation by using composition by the andThen step as in:

MethodCall.invoke(declaredConstructor).with("message")
  .andThen(MethodDelegation.to(DefaultConstructorInterceptor.class));

Upvotes: 2

Related Questions