使用bytebuddy是否可以增强在注释具有特定属性值的地方进行注释的字段?

时间:2019-05-02 22:11:15

标签: java byte-buddy

我正在尝试使用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")
        )

我正在寻找的是做“ havingAttribute”部分的方法。这可能吗,还是我走错路了?感谢您提供任何见识。

2 个答案:

答案 0 :(得分:1)

一种方法是创建一个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

答案 1 :(得分:0)

我最终实现了这样的自定义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);
        }

    }
}

我使用此元素匹配器来确定是否应在现有的@OneToOne关系中添加@LazyToOne批注。