← Назад к вопросам

Как создать кастомную аннотацию?

2.3 Middle🔥 111 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Создание кастомной аннотации в Java

Аннотация — это форма метаданных, которая предоставляет информацию о коде без влияния на сам код. Кастомные аннотации позволяют создавать специализированные метаданные для вашего проекта.

Базовый синтаксис аннотации

import java.lang.annotation.*;

@Target(ElementType.METHOD)  // Где применяется
@Retention(RetentionPolicy.RUNTIME)  // Когда доступна
public @interface MyAnnotation {
    String value() default "default value";
}

1. Простая аннотация без параметров

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

// Использование
public class Example {
    @Deprecated
    public void oldMethod() {
        System.out.println("This method is deprecated");
    }
}

2. Аннотация с параметрами

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
    String level() default "INFO";
    boolean performanceCheck() default false;
}

// Использование
public class UserService {
    @Log(level = "ERROR", performanceCheck = true)
    public void deleteUser(Long id) {
        // Логирование с ERROR уровнем
    }
}

3. Параметры аннотации (@interface)

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {
    String[] roles() default {"USER"};
    String description() default "";
    int maxAttempts() default 3;
}

// Использование
@Auth(roles = {"ADMIN", "MODERATOR"}, description = "Delete user")
public void deleteUser(Long id) {
    // Только администраторы могут вызвать
}

4. Meta-аннотации

Meta-аннотации описывают поведение вашей аннотации:

// @Target - где использовать аннотацию
@Target({
    ElementType.TYPE,        // На классах
    ElementType.METHOD,      // На методах
    ElementType.FIELD,       // На полях
    ElementType.PARAMETER    // На параметрах
})

// @Retention - когда аннотация доступна
@Retention(RetentionPolicy.RUNTIME)  // Доступна во время выполнения
// RetentionPolicy.CLASS - в файле .class
// RetentionPolicy.SOURCE - только для компилятора

// @Documented - включается в JavaDoc
@Documented

// @Inherited - наследуется подклассами
@Inherited

public @interface ApiEndpoint {
    String path();
    String method() default "GET";
}

5. Обработка аннотаций в runtime

import java.lang.reflect.Method;

public class AnnotationProcessor {
    
    public static void processClass(Class<?> clazz) {
        Method[] methods = clazz.getDeclaredMethods();
        
        for (Method method : methods) {
            if (method.isAnnotationPresent(Log.class)) {
                Log logAnnotation = method.getAnnotation(Log.class);
                System.out.println("Method: " + method.getName());
                System.out.println("Log level: " + logAnnotation.level());
                System.out.println("Performance check: " + logAnnotation.performanceCheck());
            }
        }
    }
}

// Использование
public class Main {
    public static void main(String[] args) {
        AnnotationProcessor.processClass(UserService.class);
    }
}

6. Практический пример: Валидирующая аннотация

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidEmail {
    String message() default "Invalid email format";
}

// Использование на поле
public class User {
    @ValidEmail(message = "Email должен быть валидным")
    private String email;
}

// Обработка аннотации
public class ValidationUtil {
    public static void validate(Object object) {
        Class<?> clazz = object.getClass();
        
        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(ValidEmail.class)) {
                field.setAccessible(true);
                try {
                    String value = (String) field.get(object);
                    if (!isValidEmail(value)) {
                        ValidEmail annotation = field.getAnnotation(ValidEmail.class);
                        throw new ValidationException(annotation.message());
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    private static boolean isValidEmail(String email) {
        return email.matches("^[A-Za-z0-9+_.-]+@(.+)$");
    }
}

7. Аннотация с массивом значений

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Permissions {
    String[] value();
}

// Использование
@Permissions({"read", "write", "delete"})
public void manageData() {
    // Метод требует разрешений
}

Сравнение типов аннотаций

ТипПримерИспользование
Без параметров@OverrideПросто маркер
С параметром@Log(level="ERROR")Одно значение
Многих параметров@Auth(roles={...}, desc="...")Несколько опций
На уровне типа@ServiceНа классах
На уровне метода@RequestMappingНа методах
На уровне поля@ColumnНа переменных

Best Practices

  1. Используй @Documented для публичных аннотаций
  2. Устанавливай значения по умолчанию
  3. Ограничивай @Target только необходимыми местами
  4. Документируй назначение аннотации в JavaDoc
  5. Обрабатывай аннотации с помощью Reflection API
Как создать кастомную аннотацию? | PrepBro