Комментарии (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
- Используй @Documented для публичных аннотаций
- Устанавливай значения по умолчанию
- Ограничивай @Target только необходимыми местами
- Документируй назначение аннотации в JavaDoc
- Обрабатывай аннотации с помощью Reflection API