Bayangkan kelas yang ditakrifkan seperti berikut:
@Something(someProperty = "some value") public class Foobar { //... }
Kelas ini telah pun disusun dan tidak boleh diubah suai. Walau bagaimanapun, kami ingin menukar nilai "someProperty" secara dinamik semasa masa jalan. Adakah ini boleh dilaksanakan, dan jika ya, bagaimanakah ia boleh dicapai?
Untuk mengubah suai nilai anotasi pada masa jalan, kami boleh memanfaatkan refleksi dan proksi dinamik. Coretan berikut menunjukkan pendekatan ini:
public static Object changeAnnotationValue(Annotation annotation, String key, Object newValue){ Object handler = Proxy.getInvocationHandler(annotation); Field f; try { f = handler.getClass().getDeclaredField("memberValues"); } catch (NoSuchFieldException | SecurityException e) { throw new IllegalStateException(e); } f.setAccessible(true); Map<String, Object> memberValues; try { memberValues = (Map<String, Object>) f.get(handler); } catch (IllegalArgumentException | IllegalAccessException e) { throw new IllegalStateException(e); } Object oldValue = memberValues.get(key); if (oldValue == null || oldValue.getClass() != newValue.getClass()) { throw new IllegalArgumentException(); } memberValues.put(key,newValue); return oldValue; }
Pendekatan ini boleh digunakan dalam pelbagai senario. Sebagai contoh, berikut ialah contoh yang melibatkan jenis anotasi yang berbeza:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ClassAnnotation { String value() default ""; } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface FieldAnnotation { String value() default ""; } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MethodAnnotation { String value() default ""; } @ClassAnnotation("class test") public static class TestClass{ @FieldAnnotation("field test") public Object field; @MethodAnnotation("method test") public void method(){ } }
Dengan persediaan ini, kami boleh mengubah suai nilai anotasi secara dinamik:
public static void main(String[] args) throws Exception { final ClassAnnotation classAnnotation = TestClass.class.getAnnotation(ClassAnnotation.class); System.out.println("old ClassAnnotation = " + classAnnotation.value()); changeAnnotationValue(classAnnotation, "value", "another class annotation value"); System.out.println("modified ClassAnnotation = " + classAnnotation.value()); Field field = TestClass.class.getField("field"); final FieldAnnotation fieldAnnotation = field.getAnnotation(FieldAnnotation.class); System.out.println("old FieldAnnotation = " + fieldAnnotation.value()); changeAnnotationValue(fieldAnnotation, "value", "another field annotation value"); System.out.println("modified FieldAnnotation = " + fieldAnnotation.value()); Method method = TestClass.class.getMethod("method"); final MethodAnnotation methodAnnotation = method.getAnnotation(MethodAnnotation.class); System.out.println("old MethodAnnotation = " + methodAnnotation.value()); changeAnnotationValue(methodAnnotation, "value", "another method annotation value"); System.out.println("modified MethodAnnotation = " + methodAnnotation.value()); }
Kod ini menunjukkan keupayaan untuk menukar nilai anotasi yang dikaitkan dengan kelas, medan dan kaedah pada masa jalan.
Atas ialah kandungan terperinci Bolehkah Kami Mengubah Suai Parameter Rentetan Anotasi Java pada Runtime?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!