Карта / Spring Core / @Component, @Autowired

@Component, @Autowired

@Component помечает класс как бин — Spring сам создаст его объект и будет им управлять. @Service, @Repository, @Controller — это специализированные версии @Component для разных слоёв приложения (по сути то же самое, но имя точнее отражает роль класса).

@Component
class EmailValidator {
    boolean isValid(String email) { return email.contains("@"); }
}

@Service
class UserService {
    private final EmailValidator validator;

    @Autowired                       // "внедри сюда нужную зависимость"
    UserService(EmailValidator validator) {
        this.validator = validator;
    }
}

@Autowired говорит Spring: «найди подходящий бин и подставь его сюда». Если бин с таким типом существует в контейнере — Spring сам передаст его в конструктор.

Копнуть глубже

@Autowired на конструкторе можно опустить, если конструктор один — современный Spring сам понимает, что нужно внедрить зависимости, без явной аннотации:

@Service
class UserService {
    private final EmailValidator validator;
    UserService(EmailValidator validator) {   // @Autowired не нужен — конструктор единственный
        this.validator = validator;
    }
}

Внедрение через конструктор — рекомендуемый способ, а не через поле (@Autowired private EmailValidator validator;):

  • Поле нельзя сделать final — теряется гарантия неизменности зависимости;
  • Объект нельзя создать без зависимостей (в обычном new, без Spring) — конструктор делает зависимости явными и обязательными;
  • Проще тестировать — просто передаёшь mock в конструктор, не нужна рефлексия.

Что если бинов подходящего типа несколько? Spring не сможет понять, какой использовать, и упадёт с ошибкой — для этого случая есть @Qualifier, разобранный отдельно в теме «Scope, @Qualifier».

🎤 Закрыл тему, если можешь объяснить:
• что делает `@Component` и `@Autowired`;
• почему внедрение через конструктор предпочтительнее, чем через поле (если дошёл до 2-го слоя).