Аннотациями являются некие метаданные, которые способны добавляться в исходный код программы и семантически не влияют на нее, но способны использоваться в процессе анализа кода, компиляции и даже во время выполнения.
Возможности использования аннотаций:
- предоставлять необходимую информацию для компилятора;
- предоставлять метаданные различным инструментам для генерации кода, конфигураций и т.д.;
- использоваться в коде во время выполнения программного кода (reflection).
Для описания новой аннотации используется ключевое слово @interface.
Реализация:
public @interface Description {
String title();
int version() default 1;
String text();
}
Пример ее использования:
@Description(title="title", version=2, text="text")
public class Clazz { /* */ }
Если у аннотации нет элементов, ее называют маркером (marker annotation type). В этом случае при использовании аннотации круглые скобки можно не писать.
В случае, когда аннтоация указывается для другой аннотации, первую называют мета-аннотацией (meta-annotation type).
Достаточно часто вам придется сталкиваться с мета-аннтоацией Retention. Она показывает, как долго необходимо хранить аннтоацию и инициализируется одним из трех значений:
RetentionPolicy.SOURCE - аннотация используется на этапе компиляции и должна отбрасываться компилятором;
RetentionPolicy.CLASS - аннтоация будет записана в class-файл компилятором, но не должна быть доступна во время выполнения (runtime);
RetentionPolicy.RUNTIME - аннотация будет записана в class-файл и доступна во время выполнения через reflection.
Тут есть еще один момент на которую хочу обратить ваше внимание: по умолчанию у всех аннотаций стоит RetentionPolicy.CLASS. Это мне кажется недодумкой. В исходниках JDK очень часто используется эта policy, но вот в разработке нужна именно RetentionPolicy.RUNTIME. К сожалению, ничего уже не поменяется из-за обратной совместимости.
Пришло время привести реальный пример использования аннотаций при программировании на Java.
Предположим, нам нужно ограничить доступ к некоторым функциям веб-приложения для разных пользователей. Разными словами необходимо реализовать права (permissions).
Для этого можно добавить следующее перечисление в класс пользователя:
public class User {
public static enum Permission {
USER_MANAGEMENT, CONTENT_MANAGEMENT
}
private List permissions;
public List getPermissions() {
return new ArrayList(permissions);
}
// ...
}
Создадим аннотацию, которую затем будем использовать для проверки прав:
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionRequired {
User.Permission value();
}
Теперь предположим у нас есть некоторое действие, право на выполнение которого мы хотим ограничить, например, UserDeleteAction. Мы добавляем аннтоацию на это действие следующим образом:
@PermissionRequired(User.Permission.USER_MANAGEMENT)
public class UserDeleteAction {
public void invoke(User user) { /* */ }
}
Теперь используя reflection можно принимать решение, разрешать или не разрешать выполнение определенного действия:
User user = ...;
Class actionClass = ...;
PermissionRequired permissionRequired =
actionClass.getAnnotation(PermissionRequired.class);
if (permissionRequired != null)
if (user != null && user.getPermissions().contains(permissionRequired.value()))
// выполнить действие
Небольшая презентация
На днях напишу про рефлексию и стратегию











Комментариев нет:
Отправить комментарий