![](/img/trans.png)
[英]Annotation with AOP - works at method level while only the class is annotated
[英]Overriding method level @annotation at runtime with reflection, works for class level
問題:我能夠使用以下方法成功覆蓋類級別的注釋:
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 個可以在類級別設置,所以我用這段代碼成功地覆蓋了它們,但是如果注釋是針對方法本身的呢?
我的接口實現類:
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,這是我的代碼(這兩個接口都在類級別正常運行)
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 接口:
/**
* 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();
}
這是我在github上的代碼。 . 你可以使用
addAnnotation(...)
removeAnnotation(...)
changeAnnotationValue(...)
修改Class
、 Field
、 Method
上的注解。 並使用createAnnotationFromMap
創建任何類型注釋。
對於 JUnit4 引誘,我使用以下方法在方法級別動態設置 DisplayName。
AllureLifecycle oLifecycle = Allure.getLifecycle();
oLifecycle.updateTestCase(testResult -> testResult.setName("My DisplayName");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.