Создание аннотаций с помощью byte-buddy, но мой код не может найти аннотации - PullRequest
0 голосов
/ 28 мая 2018

В настоящее время я пытаюсь сгенерировать свои классы для своих тестов следующим образом:

AnnotationDescription entity = AnnotationDescription.Builder.ofType(Entity.class) //
    .build();

AnnotationDescription table = AnnotationDescription.Builder.ofType(Table.class) //
    .define("name", "FIRST_TABLE") //
    .build();

// @Column ( name = "X1", length = 20 )
AnnotationDescription nameAnnotationColumn = AnnotationDescription.Builder.ofType(Column.class) //
    .define("name", "X1") //
    .define("length", 20) //
    .build();

// @Column ( name = "X1", length = 20 )
AnnotationDescription nameAnnotationKeyColumn = AnnotationDescription.Builder.ofType(Column.class) //
    .define("name", "ADR_EXTERN_KEY") //
    .define("precision", 15) //
    .build();
Class<? extends Serializable> subclass = new ByteBuddy().subclass(Serializable.class) //
    .annotateType(entity, table) //
    .defineField("name", String.class, Visibility.PRIVATE).annotateField(nameAnnotationColumn) //
    .defineMethod("getName", String.class, Visibility.PUBLIC).intercept(FieldAccessor.ofField("name")) //
    .defineField("key", BigDecimal.class, Visibility.PRIVATE).annotateField(nameAnnotationKeyColumn) //
    .defineMethod("getKey", BigDecimal.class, Visibility.PUBLIC).intercept(FieldAccessor.ofField("key")) //
    .make() //
    .load(getClass().getClassLoader()) //
    .getLoaded();

Но мой собственный код пытается идентифицировать класс, который должен иметь аннотацию типа @Entity и @Table(name = "XXX"),Таким образом, вызов .annotatypeType(..), кажется, либо делает что-то, чего я не понимаю, либо я просто создаю аннотации неправильным способом.

Код, который пытается определить, содержат ли классы @Entityи @Table аннотация в целом выглядит следующим образом:

public class X {
  private Class<? extends Serializable> givenClass;

  ...

if (hasAnnotation(this.givenClass.getClass().getAnnotations(), Entity.class)) {
 ....
}

, где метод выглядит следующим образом:

  private boolean hasAnnotation(Annotation[] annotations, Object annotationToBeExistent) {

    boolean result = false;
    for (int i = 0; i < annotations.length; i++) {
      if (annotations[i].annotationType().equals(annotationToBeExistent)) {
        result = true;
      }
    }
    return result;

Если я создаю класс вручную и реализую, как обычно, код находитаннотации ... Так что я думаю, что моя ошибка должна быть где-то в использовании byte-buddy?

Обновление :

Подумав об этом и в комментарии, я обнаружил, чтомое создание было неправильным, оно должно выглядеть так:

Serializable subclass = new ByteBuddy().subclass(Object.class) //
    .implement(Serializable.class)
    .annotateType(entity, table) //

Но мой код не будет видеть созданные аннотации?

Обновление 2:

Итак, после ваших комментариев / предложений (которые мне очень помогли; спасибо за поддержку) я углубил свою проблему в следующий фрагмент кода: я предполагаю, что я использую AnnotationDescription или создаю аннотацию неправильно, потому что утверждение приведет кв false.

AnnotationDescription entity = AnnotationDescription.Builder.ofType(Entity.class) //
    .build();

Serializable subclass = new ByteBuddy().subclass(Object.class) //
    .implement(Serializable.class)
    .annotateType(entity) //
    .make() //
    .load(this.getClass().getClassLoader()) //
    .getLoaded();

assertThat (subclass.getClass (). isAnnotationPresent (Entity.class)). isTrue ();

1 Ответ

0 голосов
/ 30 мая 2018

Ваше использование API корректно, и я мог бы даже проверить работу, вызвав:

subclass.isAnnotationPresent(Entity.class)

в вашем получающемся классе.Я предполагаю, что есть проблема в вашей логике сканирования.Некоторые инструменты сканируют классы, анализируя файлы классов непосредственно из jar-файлов. Может быть, по этой причине вы не можете найти класс?

Что касается вашего обновления, ожидаете ли вы, что Byte Buddy вернет экземпляр?Byte Buddy генерирует только классы, а типы Class реализуют интерфейс Serializable, поэтому ваш код для начала компилируется:

AnnotationDescription entity = AnnotationDescription.Builder
    .ofType(Entity.class)
    .build();

Class<?> subclass = new ByteBuddy().subclass(Object.class)
  .implement(Serializable.class)
  .annotateType(entity)
  .make()
  .load(this.getClass().getClassLoader())
  .getLoaded();

Теперь результирующий класс должен содержать ожидаемую аннотацию.Вы можете использовать отражение, чтобы создать экземпляр, который реализует интерфейс Serializable.

...