Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用bytebuddy是否可以增强注释具有特定属性值的字段?_Java_Byte Buddy - Fatal编程技术网

Java 使用bytebuddy是否可以增强注释具有特定属性值的字段?

Java 使用bytebuddy是否可以增强注释具有特定属性值的字段?,java,byte-buddy,Java,Byte Buddy,我试图使用bytebuddy来重新定义现有的类。我正在寻找用特定注释注释的字段。我已经用这样的代码弄明白了: new ByteBuddy() .redefine(<some class>) .field( ElementMatchers.isAnnotatedWith(<some annotation>) ) ... new ByteBuddy() .redefine

我试图使用bytebuddy来重新定义现有的类。我正在寻找用特定注释注释的字段。我已经用这样的代码弄明白了:

new ByteBuddy()
        .redefine(<some class>)
        .field(
            ElementMatchers.isAnnotatedWith(<some annotation>)
        )
        ...
new ByteBuddy()
        .redefine(<some class>)
        .field(
            ElementMatchers.isAnnotatedWith(<some annotation>)
                .havingAttribute(<some attribute>, "value")
        )
@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
    }
}
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);
        }

    }
}
newbytebuddy()
.重新定义()
.场(
ElementMatchers.isAnnotatedWith()
)
...
我想做的是进一步细化我的ElementMatcher,以便在指定的注释中包含一个属性检查-类似这样:

new ByteBuddy()
        .redefine(<some class>)
        .field(
            ElementMatchers.isAnnotatedWith(<some annotation>)
        )
        ...
new ByteBuddy()
        .redefine(<some class>)
        .field(
            ElementMatchers.isAnnotatedWith(<some annotation>)
                .havingAttribute(<some attribute>, "value")
        )
@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
    }
}
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);
        }

    }
}
newbytebuddy()
.重新定义()
.场(
ElementMatchers.isAnnotatedWith()
.具有属性(,“值”)
)

我要找的是做“有属性”部分的方法。这是可能的还是我走错了路?任何见解都值得赞赏。

一种方法是创建一个
Advice.OffsetMapping.Factory
,它允许您在建议中注入注释值,如下所示:

new ByteBuddy()
        .redefine(<some class>)
        .field(
            ElementMatchers.isAnnotatedWith(<some annotation>)
        )
        ...
new ByteBuddy()
        .redefine(<some class>)
        .field(
            ElementMatchers.isAnnotatedWith(<some annotation>)
                .havingAttribute(<some attribute>, "value")
        )
@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
    }
}
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);
        }

    }
}
另见:

我最终实现了一个自定义ElementMatcher,如下所示:

new ByteBuddy()
        .redefine(<some class>)
        .field(
            ElementMatchers.isAnnotatedWith(<some annotation>)
        )
        ...
new ByteBuddy()
        .redefine(<some class>)
        .field(
            ElementMatchers.isAnnotatedWith(<some annotation>)
                .havingAttribute(<some attribute>, "value")
        )
@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
    }
}
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);
        }

    }
}
公共类NeedsAzytoonenoproxy扩展了ElementMatcher.Junction.AbstractBase{
公共布尔匹配(T目标){
AnnotationDescription oneToOneAnnotation=target.getDeclaredAnnotations(),类型为(OneToOne.class);
试一试{
if(onetooneanotation!=null){
OneToOne OneToOne=(OneToOne)((AnnotationDescription.Loadable)onetooneanotation.load();
FetchType FetchType=oneToOne.fetch();
返回fetchType==fetchType.LAZY;
}
返回false;
}
catch(classnotfounde异常){
抛出新的RuntimeException(e.getMessage(),e);
}
}
}

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

我是ByteBuddy的初学者,在@Advice注释方面没有跟上速度。我不知道我怎样才能用它来解决我的特殊问题。相反,我最终要做的是实现一个自定义ElementMatcher,它查找我感兴趣的特定注释,加载此注释,然后检查加载的注释上的属性值。不确定这是否是推荐的方法,但它起了作用。加载注释通常很好。我会避免在您的解决方案中使用强制转换,您可以使用Byte Buddy的API实现这一点。如果基础注释已经来自加载的类型,则基本上只需使用hoods下的反射API来访问它。