からthis answerを使用して実行時にフィールドの宣言された注釈を変更すると、新しい内部AnnotationData
オブジェクトを作成してインストールすることにより、実行時に注釈をJavaクラスに追加できます。 Field
が可能であるかどうか不思議でした。注釈を処理する方法が、とはかなり異なっているようです。Java Reflection API
私は正常に以下のクラスでField
クラスのdeclaredAnnotations
フィールドに注釈を追加することができました:
public class FieldRuntimeAnnotations {
private static final Field DECLARED_ANNOTATIONS_FIELD;
private static final Method DECLARED_ANNOTATIONS_METHOD;
static {
try {
DECLARED_ANNOTATIONS_METHOD = Field.class.getDeclaredMethod("declaredAnnotations");
DECLARED_ANNOTATIONS_METHOD.setAccessible(true);
DECLARED_ANNOTATIONS_FIELD = Field.class.getDeclaredField("declaredAnnotations");
DECLARED_ANNOTATIONS_FIELD.setAccessible(true);
} catch (NoSuchMethodException | NoSuchFieldException | ClassNotFoundException e) {
throw new IllegalStateException(e);
}
}
// Public access method
public static <T extends Annotation> void putAnnotationToField(Field f, Class<T> annotationClass, Map<String, Object> valuesMap) {
T annotationValues = TypeRuntimeAnnotations.annotationForMap(annotationClass, valuesMap);
try {
Object annotationData = DECLARED_ANNOTATIONS_METHOD.invoke(f);
// Get declared annotations
Map<Class<? extends Annotation>, Annotation> declaredAnnotations =
(Map<Class<? extends Annotation>, Annotation>) DECLARED_ANNOTATIONS_FIELD.get(f);
// Essentially copy our original annotations to a new LinkedHashMap
Map<Class<? extends Annotation>, Annotation> newDeclaredAnnotations = new LinkedHashMap<>(declaredAnnotations);
newDeclaredAnnotations.put(annotationClass, annotationValues);
DECLARED_ANNOTATIONS_FIELD.set(f, newDeclaredAnnotations);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new IllegalStateException(e);
}
}
}
しかし、フィールドの宣言クラスは、適切なReflectionData
に更新されません。だから本質的に私は宣言クラスで新しいフィールド情報を "インストール"する必要がありますが、私はどのように考え出すのか困っています。それは私が求めているものを明確に、ここに私のテストでは第三アサーションが失敗するようにするに
:
public class RuntimeAnnotationsTest {
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface TestAnnotation {}
public static class TestEntity {
private String test;
}
@Test
public void testPutAnnotationToField() throws NoSuchFieldException {
// Confirm class does not have annotation
TestAnnotation annotation = TestEntity.class.getDeclaredField("test").getAnnotation(TestAnnotation.class);
Assert.assertNull(annotation);
Field f = TestEntity.class.getDeclaredField("test");
f.setAccessible(true);
FieldRuntimeAnnotations.putAnnotationToField(f, TestAnnotation.class, new HashMap<>());
// Make sure field annotation gets set
Assert.assertNotNull(f.getAnnotation(TestAnnotation.class));
// Make sure the class that contains that field is also updated -- THIS FAILS
Assert.assertNotNull(TestEntity.class.getDeclaredField("test").getAnnotation(TestAnnotation.class));
}
}
私は私が達成しようとしているのか理解はかなりばかげているが、私は運動を楽しんでいます:D ...どんな考え?
魅力的な作品です!私は、 'Class.class'メソッド' privateGetDeclaredFields'をブール型パラメータ 'false'を持つフィールドの宣言クラスで呼び出すという重要な部分を見逃していました。ありがとうございました! – heez