gpt4 book ai didi

java - 在运行时使用反射覆盖方法级别@annotation,适用于类级别

转载 作者:行者123 更新时间:2023-12-02 12:05:22 29 4
gpt4 key购买 nike

问题:我能够使用以下方法成功覆盖类级别注释:

public static void alterClassAnnotation(Class classToLookFor, Class<? extends Annotation> annotationToAlter,Annotation annotationValue) {
if (isJDK7OrLower()) {
try {
Field annotations = Class.class.getDeclaredField(ANNOTATIONS);
annotations.setAccessible(true);
Map<Class<? extends Annotation>, Annotation> map =
(Map<Class<? extends Annotation>, Annotation>) annotations.get(classToLookFor);
map.put(annotationToAlter, annotationValue);
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
//In JDK8 Class has a private method called annotationData().
//We first need to invoke it to obtain a reference to AnnotationData class which is a private class
Method method = Class.class.getDeclaredMethod(ANNOTATION_DATA, null);
method.setAccessible(true);
//Since AnnotationData is a private class we cannot create a direct reference to it. We will have to
//manage with just Object
Object annotationData = method.invoke(classToLookFor);
//We now look for the map called "annotations" within AnnotationData object.
Field annotations = annotationData.getClass().getDeclaredField(ANNOTATIONS);
annotations.setAccessible(true);
Map<Class<? extends Annotation>, Annotation> map =
(Map<Class<? extends Annotation>, Annotation>) annotations.get(annotationData);
map.put(annotationToAlter, annotationValue);
} catch (Exception e) {
e.printStackTrace();
}
}
}

我对反射 API 感到困惑,如何修改此代码以覆盖方法级参数的值?我有 3 个注释,其中 2 个可以在类级别设置,因此我可以使用此代码成功覆盖它们,但是如果注释与方法本身不符怎么办?

我的接口(interface)实现类:

import java.lang.annotation.Annotation;

import io.qameta.allure.junit4.DisplayName;
public class DynamicDisplayName implements DisplayName {

private String value;

public DynamicDisplayName(String value) {
this.value = value;
}

@Override
public Class<? extends Annotation> annotationType() {
return null;
}

@Override
public String value() {
return value;
}

}

我已成功覆盖 Issue 和 TmsLink,这是我的代码(这两个接口(interface)在类级别都能正常运行)

Issue issue = SaveCourse.class.getAnnotation(Issue.class);
DynamicIssue altered = new DynamicIssue(issueId);
AnnotationHelper.alterClassAnnotation(SaveCourse.class, Issue.class, altered);
issue = SaveCourse.class.getAnnotation(Issue.class);


DisplayName dname = SaveCourse.class.getAnnotation(DisplayName.class);
DynamicDisplayName dna = new DynamicDisplayName(displayName);
AnnotationHelper.alterClassAnnotation(SaveCourse.class, DisplayName.class, dna);
dname = SaveCourse.class.getAnnotation(DisplayName.class);

TmsLink tmslink = SaveCourse.class.getAnnotation(TmsLink.class);
DynamicTmsLink tmsaltered = new DynamicTmsLink(testCaseId);
AnnotationHelper.alterClassAnnotation(SaveCourse.class, TmsLink.class, tmsaltered);
tmslink = SaveCourse.class.getAnnotation(TmsLink.class);

displayName接口(interface):

/**
* Used to change display name for test in the report.
*/
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface DisplayName {

String value();

}

最佳答案

这是我的 code on github. 。您可以使用

addAnnotation(...)
removeAnnotation(...)
changeAnnotationValue(...)

修改ClassFieldMethod上的注释。并使用 createAnnotationFromMap 创建任何类型注释。

关于java - 在运行时使用反射覆盖方法级别@annotation,适用于类级别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46937777/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com