Аннотация @Autowired: что к чему?

Решил рассказать немного про аннотацию @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 автоматически подставит не только сами бины, но и имена бинов в качестве ключей. Это может быть эффективно использовано, например, в паттерне «стратегия».

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