Как создать конструктор по умолчанию с ByteBuddy? - PullRequest
0 голосов
/ 09 ноября 2018

Я использую ByteBuddy и у меня есть этот код:

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;
    }
}

Мой текущий код генерации:

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();

Я хочу получить экземпляр класса A, а также хочу выполнить некоторые действия в конструкторе после вызова super(), например:

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

   // do something special..
}

Я пытался реализовать с MethodDelegation.to(DefaultConstructorInterceptor.class), но мне это не удалось.

1 Ответ

0 голосов
/ 10 ноября 2018

JVM требует, чтобы вы жестко закодировали вызов метода super в метод, который невозможен с использованием делегирования (также см. Javadoc), поэтому вы не можете использовать MethodDelegation для вызова конструктора. То, что вы можете сделать, это связать вызов метода, который у вас уже есть, и делегирование с помощью композиции с шагом andThen, как в:

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