2017-10-25 2 views
0

問題のために動作します:私はどのように、リフレクションAPIで混乱しています、クラスレベル

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(); 
      } 
     } 
    } 

私は成功し、次を使用して、クラスレベルの注釈を上書きすることができていますメソッドレベルのパラメータをオーバーライドするためにこのコードを変更できますか?私は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; 
    } 

} 

は、私が正常にオーバーライドされた問題と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(); 

} 
+0

java.lang.Classでプライベートフィールドまたはメソッドが存在することは、Javaのそれ以降のバージョンでは無効になることが保証されています。なぜあなたはこれをしたいのですか? – VGR

+0

私はテストデータ用にjunit DataProviderで魅力的なレポートを使用していますが、魅力にはメソッドレベルで適用できるいくつかの注釈がありますが、DataProviderからアノテーションにデータを渡すのに苦労しています。あなたはそのような目標を達成するためのより良い方法について助言しますか? @VGR – Jackofspace

答えて

0

ここは私のcode on github.です。あなたはClassFieldMethodに注釈を変更するには

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

を使用することができます。任意のタイプの注釈を作成するには、createAnnotationFromMapを使用します。

関連する問題