【问题标题】:With bytebuddy is it possible to enhance a field that is annotated where the annotation has a specific attribute value?使用 bytebuddy 是否可以增强带有特定属性值的注释字段?
【发布时间】:2019-05-11 00:03:40
【问题描述】:

我正在尝试使用 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”部分的方法。这是可能的还是我以错误的方式接近这个?任何见解都值得赞赏。

【问题讨论】:

    标签: java byte-buddy


    【解决方案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

    【讨论】:

    • 我是 ByteBuddy 的一个完整的初学者,并且没有跟上 @Advice 注释的速度。我不确定如何使用它来解决我的特定问题。相反,我最终做的是实现一个自定义 ElementMatcher,它查找我感兴趣的特定注释,加载此注释,然后检查加载的注释上的属性值。不确定这是否是推荐的方法,但它有效。
    • 加载注释通常没问题。我会避免在您的解决方案中进行强制转换,您可以使用 Byte Buddy 的 API 来实现这一点。如果底层注解已经来自加载的类型,您基本上只需使用底层的反射 API 访问它。
    【解决方案2】:

    我最终实现了一个这样的自定义 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 关系。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      • 2019-04-30
      • 1970-01-01
      • 1970-01-01
      • 2021-07-31
      相关资源
      最近更新 更多