Может ли bute-buddy использоваться как неотражающий способ сбора значений [field] / [method return] в виде коллекции или карты? - PullRequest
2 голосов
/ 15 апреля 2019

Я пытался найти полезный ответ, но безуспешно. Интересно, можно ли было бы использовать byte-buddy для следующего: Допустим, у нас есть POJO с количеством значений. Для определенного вида обработки меня интересуют только некоторые. Я мог бы пометить их аннотацией, например, @ConditionalData, которую я мог бы поместить в получатели или поля. Тогда я мог бы создать и inteface, скажем, NVPProvider, который бы возвращал имя поля - значение карты. Делать это с отражением возможно, но это не слишком эффективно. Я надеялся, что смогу использовать байтовый компаньон для расширения класса интерфейсом и реализации метода, но на самом деле я не нахожу, как создать реализацию для достижения этого.

Я прошел реализацию:

net.bytebuddy.implementation.Implementation

и пытался найти примеры вокруг веб-страниц, но я не нашел правильного пути.

public interface NVPProvider {
    Map<String, Object> getDataAsNVP();
}

public <O> Builder<O> instrumentType(Builder<O> builder) {
    builder.implement(NVPProvider.class).method(net.bytebuddy.matcher.ElementMatchers.named("getDataAsNVP")).intercept( ??? );        
    return builder.implement(NVPProvider.class);
}

Интересно, есть ли способ, которым я бы итерировал поля и геттеры и сопоставлял объекты Accessible путем рефлексивного получения аннотаций, однако на основе этого я мог бы составить реализацию метода интерфейса, итерируя соответствующие поля и внося вклад в В результате на карте воображаемый сгенерированный код будет выглядеть так:

Map<String, Object> result = new HashMap<>();
Object obj0 = getValue001();
result.put("getValue001", obj0);

Object ob10 = accesibleField1;
result.put("ob10 ", ob10 );

Позже я мог бы добавить атрибут аннотации для лучшего вида клавиш.

Я видел примеры с

MethodDelegation.to(interceptor)

однако, тогда я теперь вижу, как это сделать без отражения.

У меня есть идея, как это сделать с Javassist, где вы на самом деле можете создавать фрагменты кода, которые вы позже скомпилируете, но я не уверен, как это сделать с помощью byte-buddy. Я использовал byte-budy для расширения POJO с помощью простых методов получения, динамически определенных в конфигурационном файле, и это выглядит хорошо. Наличие только одного инструмента манипуляции байтами было бы чище. Спасибо за любые советы.

1 Ответ

0 голосов
/ 15 апреля 2019

Это возможно в Byte Buddy, но вам нужно будет создать собственное тело метода, реализовав свой собственный Implementation или его базовый ByteCodeAppender.Вы можете использовать ASM напрямую, поскольку такие посетители выставляют свои MethodVisitor, но немного проще, вы также можете использовать конструкции более высокого уровня, предлагаемые в пакете net.bytebuddy.implementation.bytecode .Для метода, как вы его описываете, вы должны сначала создать хэш-карту:

List<StackManipulation> m = new ArrayList<>();

// new HashMap<>();
m.add(TypeCreation.of(HashMap.class));
m.add(Duplication.SINGLE);
m.add(MethodInvocation.invoke(new MethodDescription.ForLoadedConstructor(HashMap.class.getConstructor());

Впоследствии ByteCodeAppender предлагает описание инструментированного типа, из которого вы можете перейти ко всем полям и методам, таким как:

FieldDescription field = ...

// map.put(fieldName, fieldValue);
m.add(Duplication.SINGLE);
m.add(new TextConstant(field.getName());
m.add(MethodVariableAccess.loadThis());
m.add(FieldAccess.forField(field).read());
m.add(MethodInvocation.invoke(Map.class.getMethod("put", Object.class, Object.class)));
m.add(Removal.SINGLE);

Приведенный выше код сначала дублирует хэш-карту в стеке, чтобы сохранить ее для дальнейшего доступа, затем добавляет имя поля в стек, загружает значение поля и затем вызывает метод Map::put.Наконец, он сбрасывает возвращаемое значение метода put.

Наконец, вам нужно вернуть карту, добавив MethodReturn.REFERENCE.

Вы можете посмотреть другие Implementation s в Byte Buddyчтобы увидеть, как это работает в деталях, и ASM предоставляет хорошее руководство по основам байт-кода, чтобы объяснить метафору стека, которой должны следовать шаблоны байт-кода.

...