С помощью bytebuddy возможно ли улучшить поле, которое аннотируется, когда аннотация имеет конкретное значение атрибута? - PullRequest
1 голос
/ 03 мая 2019

Я пытаюсь использовать bytebuddy для переопределения существующих классов. Я ищу поля, которые отмечены конкретной аннотацией. Я понял это с помощью кода примерно так:

new ByteBuddy()
        .redefine(<some class>)
        .field(
            ElementMatchers.isAnnotatedWith(<some annotation>)
        )
        ...

Что я хотел бы сделать, так это уточнить мой ElementMatcher, чтобы включить проверку атрибута в указанной аннотации - что-то вроде этого:

new ByteBuddy()
        .redefine(<some class>)
        .field(
            ElementMatchers.isAnnotatedWith(<some annotation>)
                .havingAttribute(<some attribute>, "value")
        )

То, что я ищу, - это способ выполнения части «hasAttribute». Возможно ли это, или я подхожу к этому неправильно? Любое понимание приветствуется.

Ответы [ 2 ]

1 голос
/ 03 мая 2019

Один из подходов заключается в создании Advice.OffsetMapping.Factory, который позволяет вводить значение аннотации в ваш совет следующим образом:

@Advice.OnMethodEnter(suppress = Throwable.class)
public static void onMethodEnter(@AnnotationValueExtractor(annotationClassName = "co.elastic.apm.api.CaptureSpan", method = "value") String spanName) {
    if (spanName.equals("foo")) {
        // do something special
    }
}

См. Также: https://github.com/elastic/apm-agent-java/blob/f6781c3d740602f000332f9b4a5b5ecb0d01627a/apm-agent-core/src/main/java/co/elastic/apm/agent/bci/bytebuddy/AnnotationValueOffsetMappingFactory.java

0 голосов
/ 10 мая 2019

Я закончил тем, что реализовал собственный ElementMatcher следующим образом:

public class NeedsLazyToOneNoProxy<T extends AnnotationSource> extends ElementMatcher.Junction.AbstractBase<T> {


    public boolean matches(T target) {
        AnnotationDescription oneToOneAnnotation = target.getDeclaredAnnotations().ofType(OneToOne.class);
        try {
            if (oneToOneAnnotation != null) {
                OneToOne oneToOne = (OneToOne) ((AnnotationDescription.Loadable) oneToOneAnnotation).load();
                FetchType fetchType = oneToOne.fetch();
                return fetchType == FetchType.LAZY;
            }
            return false;
        }
        catch (ClassNotFoundException e) {
            throw new RuntimeException(e.getMessage(), e);
        }

    }
}

Я использую этот элемент сопоставления, чтобы определить, нужно ли мне добавлять аннотацию @LazyToOne к существующему отношению @OneToOne.

...