2016-07-01 2 views
1

Я пытаюсь выяснить, как установить значение поля экземпляра с помощью Byte Buddy. В документации написано:Установите экземплярField в Byte Buddy

Всегда помните о назначении значения этому полю перед вызовом методов в экземпляре такого динамического класса. В противном случае делегирование метода приведет к исключению NullPointerException.

Но я не вижу нигде в документации или модульных тестах, как это сделать.

Мой динамический класс:

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

Я вижу еще один пост с ответом на перехват любой конструктор и использовать @FieldProxy с MethodDelegation, но я не вижу, как это сделать. Все, что я пытался с точки зрения результатов в какой-то вариации .constructor(ElementMatchers.any()).intercept(...) результатов в:

java.lang.IllegalArgumentException: Ни один из [] не позволяет делегации ...

ответ

0

В основном, когда вы используют MethodDelegation.toInstanceField, Byte Buddy добавляет поле данного имени к сгенерированному классу. В вашем случае Байт Бадди добавил поле типа service по имени "consumer".

Теперь вам нужно решить, как вы хотите присвоить значение этому полю, поскольку поле не имеет значения, то есть null перед назначением. Если вы вызвали метод, который был аннотирован @Start, перед этим вы столкнулись с NullPointerException.

Самый простой способ присвоить поле будет отражением. Альтернатива типобезопасной бы реализовать некоторый интерфейс

interface SetterIFace { 
    void setConsumer(MyType myType); 
} 

при условии, что ваш service типа является Class<MyType>. Затем можно добавить:

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

реализовать SetterIFace как сеттер поля в вопросе после того, как вы определили его в MethodDelegation.

Смежные вопросы