Карта / ООП / Аннотации

Аннотации

Аннотация — метка на коде, которую читают компилятор, фреймворк или инструменты. Не меняет логику напрямую, но говорит «обращайся с этим особым образом».

Вы уже использовали их каждый день в Spring:

@RestController          // Spring: сделай этот класс HTTP-контроллером
@GetMapping("/users")    // Spring: этот метод обрабатывает GET /users
@Override                // компилятор: проверь что я правда переопределяю
@Deprecated              // инструменты: предупреди что метод устарел
@SuppressWarnings("all") // компилятор: не показывай предупреждения

Своя аннотация:

@Retention(RetentionPolicy.RUNTIME)  // доступна в рантайме (нужно для рефлексии)
@Target(ElementType.METHOD)          // можно ставить только на методы
public @interface LogExecutionTime {
    String value() default "";       // параметр с дефолтом
}

@Retention — когда аннотация живёт:

  • SOURCE — только в исходниках, компилятор удаляет (например @Override)
  • CLASS — в байт-коде, но недоступна в рантайме
  • RUNTIME — доступна через рефлексию в рантайме (все Spring-аннотации)
Копнуть глубже

Как фреймворки читают аннотации через рефлексию:

// Spring внутри делает что-то похожее
for (Method method : bean.getClass().getMethods()) {
    if (method.isAnnotationPresent(LogExecutionTime.class)) {
        LogExecutionTime ann = method.getAnnotation(LogExecutionTime.class);
        // оборачивает вызов метода в прокси с таймером
    }
}

Это именно то, как работает AOP в Spring (см. тему «AOP: Aspect, Advice, Pointcut»): Spring сканирует классы, находит аннотации, создаёт прокси.

@Target — куда можно ставить аннотацию:

ElementType.TYPE        // класс, интерфейс, enum
ElementType.METHOD      // метод
ElementType.FIELD       // поле
ElementType.PARAMETER   // параметр метода
ElementType.CONSTRUCTOR // конструктор

Мета-аннотации — аннотации на аннотациях. @Retention и @Target сами являются мета-аннотациями. Ещё одна важная — @Inherited: позволяет аннотации на классе наследоваться подклассами.

Annotation Processor — обработка аннотаций на этапе компиляции (не рантайм). Примеры: Lombok генерирует геттеры/сеттеры, MapStruct генерирует маппинг-код. Работает через javax.annotation.processing.Processor — компилятор вызывает процессор до генерации байт-кода.

🎤 Закрыл тему, если можешь объяснить:
• что такое аннотация и зачем она нужна — на примере Spring;
• разницу @Retention SOURCE/CLASS/RUNTIME и как фреймворки читают аннотации (если дошёл до 2-го слоя).