Несколько дней новогоднего волшебства:
Успейте начать обучение в 2018-ом году со скидкой до 30%!
Выбрать курс

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

Spring_Deep_13.06_Site_NEW.png

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

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

Автор
9 комментариев
2
  1. Spring поддерживает Inject, но разница есть. В частности в возможностях Autowired и как inject.* аннотации соотносятся со спринговыми. На курсе мы эту разницу, в частности, рассмотрим.
  2. Получится, но там не просто "ленивая" там целый lifecycle как будут задаваться эти поля и зависят от некоторых факторов.
  3. На курсе мы бины рассмотрим и на уровне Junior и на уровне Middle для фанатов, приходите)
1

Напишите пожалуйста разницу между @org.springframework.beans.factory.annotation.Autowired и @javax.inject.Inject при работе с Spring.

  • опишите пожалуйста ленивая ли (lazy) инициализация полей? Например классы Husband и Wife и они оба имеют ссылку друг на друга.
  • хотелось бы описания для уровня Middle, а не Junior, которые в первый раз видят Spring
2
  1. Spring поддерживает Inject, но разница есть. В частности в возможностях Autowired и как inject.* аннотации соотносятся со спринговыми. На курсе мы эту разницу, в частности, рассмотрим.
  2. Получится, но там не просто "ленивая" там целый lifecycle как будут задаваться эти поля и зависят от некоторых факторов.
  3. На курсе мы бины рассмотрим и на уровне Junior и на уровне Middle для фанатов, приходите)
1
  1. На курсе мы бины рассмотрим на уровне Junior, приходите)

возможно это значит наоборот, не приходите? =) С Spring я работаю года 4, а вот с Spring Boot опыта на проде всего полгода и то версии 1.5, а вы 2 версию рассматриваете. То есть именно уровень Middle для Spring Boot очень бы подошёл.

2
  1. И на миддл и на джуниор) Поправил)
  2. Ну вообще курс многогранный, от простых вещей, до оченб сложных архитектурных. В среднем Middle с хвостиком и получится
1

Дим, привет! Ну а что ты хотел) Первая строчка в описании курса: "Первая строчка в резюме выпускников, которая появится после курса, будет звучать так: «Умею выживать в проектах, где есть Spring»"знаний!

0

Сергей, привет! Только не говори, что я придираюсь =)

PS: удалите пожалуйста лишний комментарий =)

0

Тем более ты уже проходил курсы OTUS :) И знаешь что большинство курсов нацелено на людей без углубленных знаний

0

Сергей, привет! Только не говори, что я придираюсь =)

0
@Autowired
private Map<String, StringCallable> map;

Обожаю такие красивые решения! То что доктор прописал! Спасибо!

Для комментирования необходимо авторизоваться