Аннотация @Autowired: что к чему?
2026-03-10 21:42 Diff

Теги: servicedependency, myservice, @autowired, servicedependencyimpl, private-поля, конструктор, сеттеры, @qualifier, типизированные коллекции, @order, паттерн стратегия

Решил рассказать немного про аннотацию @Autowired. Принцип её работы очень прост.

Допустим у нас есть bean-зависимости:

@Configuration public class Config { // тип бина - ServiceDependency, имя - dependency public ServiceDependency dependency() { return new ServiceDependencyImpl() } }

И есть класс сервиса:

@Service public class MyService { private ServiceDependency dependency; @Autowired public MyService(ServiceDependency dependency) { this.dependency = dependency; } }

И при создании контекста Spring автоматически определит, что для создания MyService требуется bean типа ServiceDependency (или наследник), найдёт его у себя, в рамках подставит зависимость ServiceDependencyImpl в bean MyService.

На самом деле, начиная со Spring 4.0 аннотацию @Autowired можно не ставить на конструктор, если он единственный в классе.

Другие варианты использования аннотации

@Autowired можно ставить непосредственно на поле. Да-да, это будет работать и с private-полями:

@Service public class MyService { @Autowired private ServiceDependency dependency; // бизнес-методы }

Также аннотацию можно ставить на сеттеры:

@Service public class MyService { private ServiceDependency dependency; @Autowired public void setDependency(ServiceDependency dependency) { this.dependency = dependency; } }

Но можно так же ставить и на отдельные методы, например:

@Service public class MyService { private ServiceDependency dependency; @Autowired public void init(ServiceDependency dependency) { this.dependency = dependency; } }

Что ещё?

Предположим, что бинов типа ServiceDependency несколько (допустим dependency1 и dependency2). Тогда, чтобы задать конкретный bean, необходимо использовать аннотацию @Qualifier:

@Service public class MyService { private ServiceDependency dependency; @Autowired public void setDependency( @Qualifier("dependency1") ServiceDependency dependency ) { this.dependency = dependency; } }

А если мы захотим использовать все бины?

Сделать это можно простым способом:

@Service public class MyService { private ServiceDependency[] dependencies; @Autowired public void setDependency(ServiceDependency[] dependencies) { this.dependency = dependency; } }

И Spring вставит (удивительно) все бины, реализующие интерфейс ServiceDependency. То же самое верно и для типизированных коллекций. Как ни странно, но порядком следования в этой коллекции можно управлять с помощью аннотации @Order.

Но самое замечательное, вот это:

@Autowired private Map<String, StringCallable> map;

Spring автоматически подставит не только сами бины, но и имена бинов в качестве ключей. Это может быть эффективно использовано, например, в паттерне «стратегия».

Есть вопрос? Напишите в комментариях!