Вопрос 26 · Раздел 5

Что делает аннотация @Autowired?

4. Избегайте static полей 5. Collection → все бины типа 6. AOT → рефлексия заменяется на прямой код

Версии по языкам: English Russian Ukrainian

🟢 Junior Level

@Autowired — указывает Spring внедрить зависимость.

@Service
public class OrderService {
    
    @Autowired  // Spring сам найдёт и внедрит OrderRepository
    private OrderRepository repo;
}

Где работает:

  • Конструктор
  • Поля
  • Сеттеры

Правило:

  • Один бин типа → внедрит его
  • Несколько → ошибка или @Qualifier

🟡 Middle Level

AutowiredAnnotationBeanPostProcessor

Обработка @Autowired:
  1. Сканирует поля/методы/конструкторы
  2. Создаёт InjectionMetadata (кэш)
  3. Ищет подходящие бины
  4. Внедряет через рефлексию

Алгоритм поиска

1. По типу (byType) — Spring находит все бины этого типа
2. Если несколько — @Qualifier фильтрует по имени
3. Если нет @Qualifier — проверяется @Primary (глобальная метка «по умолчанию»)
4. Если нет @Primary — по имени переменной (byName)

Constructor Injection (рекомендуется)

@Service
public class OrderService {
    private final OrderRepository repo;
    
    // Один конструктор → @Autowired не нужен!
    public OrderService(OrderRepository repo) {
        this.repo = repo;
    }
}

Внедрение коллекций

// Все бины типа PaymentService
@Autowired
List<PaymentService> payments;

// Map: имя бина → бин
@Autowired
Map<String, PaymentService> paymentMap;

🔴 Senior Level

ObjectProvider

@Autowired
ObjectProvider<PaymentService> provider;

// Ленивое получение
PaymentService service = provider.getIfAvailable();

// Stream всех бинов
provider.stream().forEach(...);

// Разрешение циклов!

Reflection Overhead

Field Injection → setAccessible(true) → рефлексия
  → + overhead при инициализации
  
Constructor Injection → прямой вызов
  → Быстрее
  
AOT (GraalVM) → рефлексия → прямой код
  → Нет overhead от рефлексии (setAccessible). Зависимости разрешаются на этапе компиляции.

Production Experience

Реальный сценарий: static поле

@Autowired
private static Repo repo;  // НЕ работает!

// Spring внедряет в экземпляры, не в классы
// → repo = null

Best Practices

  1. Constructor → по умолчанию
  2. @Autowired не нужен для одного конструктора
  3. ObjectProvider → для циклов и лени
  4. Избегайте static полей
  5. Collection → все бины типа
  6. AOT → рефлексия заменяется на прямой код

Резюме для Senior

  • AutowiredAnnotationBeanPostProcessor (AABPP) → обработка @Autowired
  • Constructor → быстрее, final поля
  • ObjectProvider → ленивое, циклы
  • static → не работает
  • Collection → все бины типа
  • AOT → нет рефлексии в Native Image

🎯 Шпаргалка для интервью

Обязательно знать:

  • @Autowired обрабатывается AutowiredAnnotationBeanPostProcessor — сканирует поля/методы/конструкторы
  • Алгоритм: byType → @Qualifier → @Primary → byName → ошибка
  • Constructor Injection — рекомендуемый подход; с одним конструктором @Autowired не нужен
  • Внедрение коллекций: List — все бины типа, Map<String, T> — имя бина → бин
  • ObjectProvider — ленивое получение, stream всех бинов, разрешение циклических зависимостей
  • @Autowired на static полях НЕ работает — Spring внедряет в экземпляры, не в классы
  • Constructor Injection быстрее Field Injection: прямой вызов vs рефлексия (setAccessible)

Частые уточняющие вопросы:

  • Что будет, если два бина одного типа без @Qualifier? — NoUniqueBeanDefinitionException (если нет @Primary или совпадения по имени).
  • Как разрешить циклическую зависимость? — ObjectProvider.getIfAvailable() или setter/field injection вместо constructor.
  • Почему Constructor Injection рекомендуется? — Immutable поля (final), нет рефлексии, легче тестировать, явные зависимости.
  • Работает ли @Autowired в GraalVM Native Image? — Да, но рефлексия заменяется на прямой код при AOT-компиляции.

Красные флаги (НЕ говорить):

  • «@Autowired на static поле работает» — нет, Spring не внедряет в статические поля.
  • «Spring ищет бин по имени в первую очередь» — нет, сначала byType, потом byName.
  • «Field Injection лучше Constructor Injection» — наоборот, constructor даёт immutable и тестируемость.
  • «@Autowired всегда обязателен» — нет, с одним конструктором Spring внедряет автоматически.

Связанные темы:

  • [[27. Что делать, если есть несколько бинов одного типа]]
  • [[28. Что такое @Qualifier]]
  • [[24. Что такое @Configuration класс]]
  • [[25. В чём разница между @Component, @Service, @Repository, @Controller]]