1. Обзор
Аннотации , форма метаданных, которую вы можете добавить в код Java. Эти аннотации могут быть обработаны во время компиляции и встроены в файлы классов или могут быть сохранены и доступны во время выполнения с помощью Отражения .
В этой статье мы обсудим, как изменить аннотацию значение во время выполнения с помощью Отражения . В этом примере мы будем использовать аннотации уровня класса.
2. Аннотация
Java позволяет создавать новые аннотации используя существующие. В простейшей форме аннотация представляется в виде @ символ, за которым следует название аннотации:
@Override
Давайте создадим нашу собственную аннотацию Более значительный :
@Retention(RetentionPolicy.RUNTIME) public @interface Greeter { public String greet() default ""; }
Теперь мы создадим класс Java Приветствия , который использует аннотацию уровня класса |:
@Greeter(greet="Good morning") public class Greetings {}
Теперь мы получим доступ к значению аннотации с помощью отражения. Класс Java Класс предоставляет метод getAnnotation для доступа к аннотациям класса:
Greeter greetings = Greetings.class.getAnnotation(Greeter.class); System.out.println("Hello there, " + greetings.greet() + " !!");
3. Измените Аннотацию
Класс Java Класс поддерживает карту для управления аннотациями – Аннотации класс в качестве ключей и Аннотации объект в качестве значения:
Map, Annotation> map;
Мы обновим эту карту, чтобы изменить аннотацию во время выполнения. Подход к доступу к этой карте отличается в различных реализациях JDK. Мы обсудим это для JDK7 и JDK8.
3.1. Реализация JDK 7
Класс Java Класс имеет поле |/аннотации . Поскольку это закрытое поле, чтобы получить к нему доступ, мы должны установить доступность поля в true . Java предоставляет метод getDeclaredField для доступа к любому полю по его имени:
Field annotations = Class.class.getDeclaredField(ANNOTATIONS); annotations.setAccessible(true);
Теперь давайте получим доступ к карте аннотаций для класса Встречающий :
Map, Annotation> map = annotations.get(targetClass);
Теперь это карта, которая содержит информацию обо всех аннотациях и их объекте значения. Мы хотим изменить Более значительный значение аннотации, которое мы можем получить, обновив объект аннотации Более значительный класс:
map.put(targetAnnotation, targetValue);
3.2. Реализация JDK 8
Реализации Java 8 хранят аннотации информацию внутри класса Данные аннотации . Мы можем получить доступ к этому объекту с помощью метода данные аннотации . Мы установим доступность для данных аннотации метода в true , поскольку это частный метод:
Method method = Class.class.getDeclaredMethod(ANNOTATION_METHOD, null); method.setAccessible(true);
Теперь мы можем получить доступ аннотации поле. Поскольку это поле также является закрытым полем, мы установим доступность для истинный :
Field annotations = annotationData.getClass().getDeclaredField(ANNOTATIONS); annotations.setAccessible(true);
В этом поле есть карта кэша аннотаций, в которой хранятся класс аннотаций и объект значения. Давайте изменим это:
Map, Annotation> map = annotations.get(annotationData); map.put(targetAnnotation, targetValue);
4. Применение
Давайте возьмем этот пример:
Greeter greetings = Greetings.class.getAnnotation(Greeter.class); System.err.println("Hello there, " + greetings.greet() + " !!");
Это будет приветствие “Доброе утро”, поскольку именно это значение мы предоставили аннотации.
Теперь мы создадим еще один объект Большего
типа со значением “Добрый вечер”:
Greeter targetValue = new DynamicGreeter("Good evening");
Давайте обновим карту аннотаций новым значением:
alterAnnotationValueJDK8(Greetings.class, Greeter.class, targetValue);
Давайте еще раз проверим значение приветствия:
greetings = Greetings.class.getAnnotation(Greeter.class); System.err.println("Hello there, " + greetings.greet() + " !!");
Он поприветствует вас как “Добрый вечер”.
5. Заключение
Реализации Java используют два поля данных для хранения данных аннотаций: аннотации , Заявленные примечания . Разница между этими двумя: сначала также сохраняются аннотации из родительских классов, а затем сохраняются только для текущего класса.
Поскольку реализация getAnnotation отличается в JDK 7 и JDK 8, мы используем здесь аннотации карту полей для простоты.
И, как всегда, исходный код реализации доступен на Github .