It's not a very common story, but you may want to dynamically change a class that has annotations like @Data (key = "1") to @Data (key = "2").
Java8 seems to have additional functions in such cases, so I referred to the following site.
public class DynamicAnnotationReplaceUtils {
private static final String ANNOTATIONS = "annotations";
private static final String ANNOTATION_DATA = "annotationData";
/**
*Replaces an annotation of one class with another annotation.
*
* @since
*
* @param targetClazz This class sets the annotation to be replaced.
* @param originalOne Annotation of the replacement source.
* @param newOne Annotation to replace. It will often be an instance of a class that extends the annotation of the replacement source.
*/
public static void annotationReplacedBy(Class<?> targetClazz, String originalName, Annotation newOne) {
try {
@SuppressWarnings("all")
Method method = Class.class.getDeclaredMethod(ANNOTATION_DATA, null);
method.setAccessible(true);
Object annotationData = method.invoke(targetClazz);
Field annotations = annotationData.getClass().getDeclaredField(ANNOTATIONS);
annotations.setAccessible(true);
@SuppressWarnings("unchecked")
Map<Class<? extends Annotation>, Annotation> map =
(Map<Class<? extends Annotation>, Annotation>) annotations.get(annotationData);
Annotation original = map.entrySet().stream().filter(e -> {
return e.getKey().getSimpleName().equals(originalName());
}).findFirst().get().getValue();
if (original == null) {
throw new IllegalArgumentException(
String.format("Class(%s) has not %s annotaion.",
targetClazz.getCanonicalName(), originalName));
}
map.put(original, newOne);
} catch (Exception ex) {
throw new IllegalArgumentException(ex);
}
}
DynamicAnnotationReplaceUtils.annotationReplacedBy(AnnotatedCalss.class, "Data", new ReplacedData()),
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Data {
public abstract String key();
}
public ReplacedData implements Data {
public String key() {
return "2";
}
}
@Data(key = "1")
public TestData() {
}
Recommended Posts