2016-07-01 27 views
1

Ich versuche herauszufinden, wie Sie den Wert eines Instanzfeldes mit Byte Buddy setzen. Die Dokumentation lautet:Setzen Sie ein instanceField in Byte Buddy

Denken Sie immer daran, diesem Feld einen Wert zuzuweisen, bevor Sie Methoden für eine Instanz einer solchen dynamischen Klasse aufrufen. Andernfalls führt eine Delegierung der Methode zu einer NullPointerException.

Aber ich sehe nirgendwo in der Dokumentation oder der Unit-Tests, wie dies zu tun ist.

Meine dynamische Klasse:

new ByteBuddy().subclass(AbstractService.class) 
     .name(serviceName) 
     .method(ElementMatchers.named("start").and(
       ElementMatchers.takesArguments(0))) 
     .intercept(
       MethodDelegation.toInstanceField(service, "consumer") 
        .filter(ElementMatchers.isAnnotatedWith(Start.class))) 
     .method(ElementMatchers.named("stop").and(
       ElementMatchers.takesArguments(0))) 
     .intercept(
       MethodDelegation.to(instance).filter(
         ElementMatchers.isAnnotatedWith(Stop.class))) 
     .make(); 

Ich sehe eine andere Stelle mit einer Antwort jeden Konstruktor abzufangen und verwenden @FieldProxy mit einem MethodDelegation aber ich sehe nicht, wie es zu tun. Alles, was ich habe in in einigen Variationen von .constructor(ElementMatchers.any()).intercept(...) Ergebnisse in Bezug auf die Ergebnisse versucht:

java.lang.IllegalArgumentException: Keine [] ermöglicht Delegation ...

Antwort

0

Grundsätzlich, wenn Sie verwenden MethodDelegation.toInstanceField, Byte Buddy fügt der generierten Klasse ein Feld des angegebenen Namens hinzu. In Ihrem Fall hat Byte Buddy ein Feld vom Typ service mit dem Namen "consumer" hinzugefügt.

Sie müssen nun entscheiden, wie Sie diesem Feld einen Wert zuweisen möchten, da das Feld keinen Wert hat, d. H. Vor der Zuweisung null ist. Wenn Sie eine Methode aufgerufen haben, die zuvor mit @Start versehen wurde, würden Sie auf NullPointerException stoßen.

Die einfachste Methode, das Feld zuzuweisen, wäre die Reflexion. Eine typsichere Alternative wäre, eine Schnittstelle

interface SetterIFace { 
    void setConsumer(MyType myType); 
} 

gegeben zu implementieren, dass Ihr service Typ ist ein Class<MyType>. Sie können dann:

.implement(SetterIFace.class).intercept(FieldAccessor.ofBeanProperty()) 

SetterIFace als Setter von dem betreffenden Gebiet zu implementieren, nachdem Sie es in den MethodDelegation definiert.