Создание пользовательских аннотаций в Java



Книга Создание пользовательских аннотаций в Java

В предыдущей статье мы говорили о том, что такое аннотации и как пользоваться готовыми аннотациями в Java. Но Java также дает возможность создавать собственные аннотации для улучшения кода. Чтобы сгенерировать любую пользовательскую аннотацию, необходимо использовать мета-аннотации. В этой статье объясняется, как создавать мета- и пользовательские аннотации и украшать ими объекты. 


Пользовательские аннотации


Наряду со множеством предопределенных аннотаций в Java можно определять и собственные пользовательские аннотации. Самодельные аннотации дают следующие преимущества.


  • Сокращают затраты на написание кода, добавляя к методам поведение по умолчанию.
  • Добавляют настраиваемое поведение классам и интерфейсам.
  • Экономят усилия на написании XML-дескрипторов и интерфейсов-маркеров.

Чтобы определить любую пользовательскую аннотацию, сначала нужно объявить ее с помощью тега @interface. Затем мы определяем цель и область применения через мета-аннотации. Работа с мета-аннотациями (@Retention, @Target, @Inherited) объясняется во второй половине этой статьи. Пользовательские аннотации могут быть определены на трех уровнях:


  • уровень класса;
  • уровень поля;
  • уровень метода.

Уровень класса


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.Type)
public @interface CustomAnnotation{ ... }

Приведенная выше пользовательская аннотация CustomAnnotation создана с политикой доступности во времени выполнения, и ее можно применять ко всем классам. Поскольку у нее нет методов, она служит простым маркером для обозначения нужных классов.


Здесь следует отметить, что любая пользовательская аннотация на уровне класса не может содержать никаких параметров и не должна вызывать никаких исключений. Кроме того, типы возвращаемых значений ограничены примитивами, строками, классами, перечислениями, аннотациями и их массивами, а значение по умолчанию не может быть null.


Уровень поля


Аналогично уровню класса, можно определять аннотации на уровне полей и ограничивать область действия.


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CustomAnnotation{ ... }

Уровень метода


Мы также можем объявлять аннотацию с доступностью во время выполнения, чтобы применять ее к методам классов:


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CustomAnnotation{ ... }

Применение пользовательских аннотаций


Вот пример, демонстрирующий использование пользовательских аннотаций.


Речь идет о двух классах: автомобиле Car и двигателе Engine. Предположим, что BasicEngine должен применяться ко всем типам автомобилей. В этом случае можно разработать пользовательскую аннотацию, такую как @BasicEngine, и аннотировать все виды реализаций автомобиля (например, хэтчбеки, спортивные автомобили, седаны и т.д.) через BasicEngine.


Пользовательская аннотация класса (интерфейса):


import java.lang.annotation.*;
@Inherited
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)

@interface BasicEngine {
String mileage() default "20";
String fuelType() default "Gasoline";
}

Класс, использующий пользовательскую аннотацию (нет необходимости в импорте):


@BasicEngine(bId="30", bName="BioDiesel")
public class Car {
String make;
String model; public Car(String make, String model){
this.make = make;
this.model = model;
}

public void getCarDetails(){
System.out.println("Car Manufacturer: " + make);
System.out.println("Car Model: " + model);
}
}

Класс водителя (Driver) для проверки вышеизложенного:


import java.lang.annotation.Annotation;
public class TestCustomAnnotationBasicEngine {

public static void main(String[] args) throws Exception{
Car car = new Car("32", "Diesel");
car.getCarDetails();
Class carClass = car.getClass();

Annotation testAnn = carClass.getAnnotation(BasicEngine.class);

BasicEngine engine = (BasicEngine)testAnn;

System.out.println("Mileage: " + engine.mileage());
System.out.println("Fuel Type: " + engine.fuelType());
}
}

Мета-аннотации


Мета-аннотации  —  это аннотации, применяемые к другим аннотациям для увеличения масштаба. Это очень важно, поскольку позволяет описывать аннотации, используя другие аннотации, и комбинировать аннотации.


В схему языка Java включены следующие важные мета-аннотации.


@Inherited


По умолчанию аннотация не может наследовать от своего суперкласса. Однако, если нужно наследовать аннотацию от суперкласса к подклассу, используется аннотация @Inherited.


@Inherited
public @interface CustomAnnotation { ... }

@CustomAnnotation
public class ParentClass { ... }

public class ChildClass extends ParentClass { ... }

Здесь дочерний класс ChildClass автоматически получает пользовательскую аннотацию CustomAnnotation, поскольку наследуется от родительского класса ParentClass. Дочерний класс может вызывать любую функциональность CustomAnnotation.


@Target


Области действия аннотаций основаны на требованиях метода или файла, таких как конструкторы или объявления. Мы можем ограничить применение аннотации к определенным целям с помощью аннотации @Target.


@Target(ElementType.METHOD)
public @interface CustomAnnotation{ ... }

В приведенном выше коде пользовательская аннотация CustomAnnotation ограничена только методами, т.е. поля, пакеты и т.д. не будут аннотироваться с ее помощью.


Аннотация может быть использована для любого элемента, если целевой тип не определен.


@Retention


Мета-аннотация @Retention указывает уровень, до которого будет доступна аннотация.


Существует три уровня, относительно которых Java позволяет определять политики хранения.


  • RetentionPolicy.SOURCE—  доступно на уровне исходного кода и игнорируется компилятором.
  • RetentionPolicy.CLASS— доступно компилятору во время компиляции и игнорируется JVM.
  • RetentionPolicy.RUNTIME— доступно для JVM.

@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation{ ... }

В заключение, аннотации  —  это удобный инструмент, который предоставляет Java. Их изучение очень помогает в том, чтобы стать более профессиональным разработчиком!



407   0  

Comments

    Ничего не найдено.