Аннотация @Inject по стандарту JSR 330 может быть использована вместо аннотации @Autowired из Spring в примерах, включенных в этот раздел.

Вы можете применить аннотацию @Autowired к конструкторам, как показано в следующем примере:

Java
public class MovieRecommender {
    private final CustomerPreferenceDao customerPreferenceDao;
    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
        this.customerPreferenceDao = customerPreferenceDao;
    }
    // ...
}
Kotlin
class MovieRecommender @Autowired constructor(
    private val customerPreferenceDao: CustomerPreferenceDao)

Начиная со Spring Framework 4.3, аннотация @Autowired для такого конструктора больше не нужна, если целевой бин сперва определяет только один конструктор. Однако, если доступно несколько конструкторов и нет основного конструктора по умолчанию, хотя бы один из них должен быть аннотирован @Autowired, чтобы предоставить контейнеру инструкцию, какой из них использовать.

Вы также можете применить аннотацию @Autowired к традиционным сеттерам, как показано в следующем примере:

Java
public class SimpleMovieLister {
    private MovieFinder movieFinder;
    @Autowired
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
    // ...
}
Kotlin
class SimpleMovieLister {
    @set:Autowired
    lateinit var movieFinder: MovieFinder
    // ...
}

Вы также можете применить аннотацию к методам с произвольными именами и несколькими аргументами, как показано в следующем примере:

Java
public class MovieRecommender {
    private MovieCatalog movieCatalog;
    private CustomerPreferenceDao customerPreferenceDao;
    @Autowired
    public void prepare(MovieCatalog movieCatalog,
            CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }
    // ...
}
Kotlin
class MovieRecommender {
    private lateinit var movieCatalog: MovieCatalog
    private lateinit var customerPreferenceDao: CustomerPreferenceDao
    @Autowired
    fun prepare(movieCatalog: MovieCatalog,
                customerPreferenceDao: CustomerPreferenceDao) {
        this.movieCatalog = movieCatalog
        this.customerPreferenceDao = customerPreferenceDao
    }
    // ...
}

Вы можете применять @Autowired и к полям, и даже смешивать его с конструкторами, как показано в следующем примере:

Java
public class MovieRecommender {
    private final CustomerPreferenceDao customerPreferenceDao;
    @Autowired
    private MovieCatalog movieCatalog;
    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
        this.customerPreferenceDao = customerPreferenceDao;
    }
    // ...
}
Kotlin
class MovieRecommender @Autowired constructor(
    private val customerPreferenceDao: CustomerPreferenceDao) {
    @Autowired
    private lateinit var movieCatalog: MovieCatalog
    // ...
}

Убедитесь, что ваши целевые компоненты (например, MovieCatalog или CustomerPreferenceDao) последовательно объявлены типом, который вы используете для точек внедрения, аннотированных с помощью @Autowired. В противном случае внедрение может завершиться ошибкой "соответствие типов не найдено" во время выполнения.

Для бинов, определенных на основе XML, или классов компонентов, найденных с помощью сканирования пути класса (classpath), контейнер обычно заранее знает конкретный тип. Однако для фабричных методов @Bean необходимо убедиться, что объявленный тип возврата достаточно выразителен. Для компонентов, реализующих несколько интерфейсов, или для компонентов, на которые потенциально можно ссылаться по типу их реализации, рассмотрите возможность объявления наиболее специфичного возвращаемого типа для вашего фабричного метода (по крайней мере, настолько специфичного, насколько это требуется точкам внедрения, ссылающимися на ваш бин).

Вы также можете дать Spring команду предоставить все бины определенного типа из ApplicationContext, добавив аннотацию @Autowired к полю или методу, который ожидает массив этого типа, как показано в следующем примере:

Java
public class MovieRecommender {
    @Autowired
    private MovieCatalog[] movieCatalogs;
    // ...
}
Kotlin
class MovieRecommender {
    @Autowired
    private lateinit var movieCatalogs: Array<MovieCatalog>
    // ...
}

То же самое относится и к типизированным коллекциям, как показано в следующем примере:

Java
public class MovieRecommender {
    private Set<MovieCatalog> movieCatalogs;
    @Autowired
    public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
        this.movieCatalogs = movieCatalogs;
    }
    // ...
}
Kotlin
class MovieRecommender {
    @Autowired
    lateinit var movieCatalogs: Set<MovieCatalog>
    // ...
}

Ваши целевые бины могут реализовать интерфейс org.springframework.core.Ordered или использовать аннотацию @Order или стандартную аннотацию @Priority, если вам нужно, чтобы элементы в массиве или списке были отсортированы в определенном порядке. В противном случае их порядок следует порядку регистрации соответствующих определений целевых бинов в контейнере.

Вы можете объявить аннотацию @Order на уровне целевого класса и на уровне методов @Bean потенциально для отдельных определений бинов (в случае нескольких определений, использующих один и тот же класс бинов). Значения @Order могут влиять на приоритеты в точках внедрения, но имейте в виду, что они не влияют на порядок запуска объектов-одиночек, который является ортогональной функцией, определяемой отношениями зависимости и объявлениями @DependsOn.

Обратите внимание, что стандартная аннотация javax.annotation.Priority недоступна на уровне @Bean, поскольку она не может быть объявлена для методов. Её семантика может быть смоделирована через значения @Order в сочетании с @Primary на одном бине для каждого типа.

Даже типизированные экземпляры Map могут быть автоматически найдены и связаны, если ожидаемый тип ключа - String. Значения в ассоциативных массивах (maps) содержат все бины ожидаемого типа, а ключи - соответствующие имена бинов, как показано в следующем примере:

Java
public class MovieRecommender {
    private Map<String, MovieCatalog> movieCatalogs;
    @Autowired
    public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
        this.movieCatalogs = movieCatalogs;
    }
    // ...
}
Kotlin
class MovieRecommender {
    @Autowired
    lateinit var movieCatalogs: Map<String, MovieCatalog>
    // ...
}

По умолчанию автоматический поиск и связывание не работает, если для данной точки внедрения нет подходящих бинов-кандидатов. В случае объявленного массива, коллекции или ассоциативного массива ожидается наличие хотя бы одного совпадающего элемента.

Логика работы по умолчанию - рассмотрение аннотированных методов и полей как указывающих на необходимые зависимости. Вы можете изменить эту логику, как показано в следующем примере, позволяя фреймворку пропускать точку внедрения, не удовлетворяющую условиям, пометив ее как необязательную (т.е. установив атрибут required в @Autowired как false):

Java
public class SimpleMovieLister {
    private MovieFinder movieFinder;
    @Autowired(required = false)
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
    // ...
}
Kotlin
class SimpleMovieLister {
    @Autowired(required = false)
    var movieFinder: MovieFinder? = null
    // ...
}

Необязательный метод не будет вызван вообще, если его зависимость (или одна из зависимостей в случае нескольких аргументов) недоступна. Необязательное поле в таких случаях вообще не заполняется, оставляя значение по умолчанию.

Аргументы внедренного конструктора и фабричного метода являются особым случаем, поскольку атрибут required в @Autowired имеет несколько иное значение из-за алгоритма разрешения конструктора Spring, который потенциально может работать с несколькими конструкторами. Аргументы метода конструктора и фабрики фактически необходимы по умолчанию, но с некоторыми специальными правилами в сценарии с одним конструктором, например, при многоэлементных точках введения (массивы, коллекции, ассоциативные массивы), разрешаются в пустые экземпляры, если нет подходящих бинов. Это позволяет использовать общий шаблон реализации, в котором все зависимости могут быть объявлены в уникальном многоаргументном конструкторе - например, объявлены как один публичный конструктор без аннотации @Autowired.

Только один конструктор любого класса бина может объявить @Autowired с атрибутом required, заданным в true, что указывает конструктору осуществлять автоматический поиск и связывание при использовании в качестве бина Spring. Как следствие, если атрибут required оставить в значении по умолчанию true, только один конструктор можно будет аннотировать с помощью @Autowired. Если несколько конструкторов объявляют данную аннотацию, все они должны объявить required=false, чтобы считаться компонентами-кандидатами на автоматическое обнаружение и связывание (аналогично autowire=constructor в XML). Будет выбран конструктор с наибольшим количеством зависимостей, которые могут быть удовлетворены соответствующими бинами в контейнере Spring. Если ни один из компонентов-кандидатов не может быть удовлетворен, то будет использован первичный конструктор/конструктор по умолчанию (если он есть). Аналогично, если класс объявляет несколько конструкторов, но ни один из них не аннотирован @Autowired, то будет использован первичный конструктор/конструктор по умолчанию (если он есть). Если в классе изначально объявлен только один конструктор, он всегда будет использован, даже если не аннотирован. Обратите внимание, что аннотированный конструктор не обязательно должен быть публичным.

Атрибут required аннотации @Autowired рекомендуется использовать вместо устаревшей аннотации @Required для устанавливающих методов. Установка атрибута required в false означает, что свойство не требуется для целей автоматического обнаружения и связывания, и свойство будет проигнорировано, если оно не может быть автоматически обнаружено и связано. С другой стороны, атрибут @Required является более строгим, поскольку принуждает устанавливать свойство любым способом, поддерживаемым контейнером, а если значение не определено, то возникает соответствующее исключение.

Как вариант, можно выразить необязательный характер конкретной зависимости с помощью java.util.Optional в Java 8, как показано в следующем примере:

public class SimpleMovieLister {
    @Autowired
    public void setMovieFinder(Optional<MovieFinder> movieFinder) {
        ...
    }
}

Начиная со Spring Framework 5.0, вы также можете использовать аннотацию @Nullable (любого типа в любом пакете, например, javax.annotation.Nullable из JSR-305) или просто использовать встроенную в Kotlin поддержку null-безопасности::

Java
public class SimpleMovieLister {
    @Autowired
    public void setMovieFinder(@Nullable MovieFinder movieFinder) {
        ...
    }
}
Kotlin
class SimpleMovieLister {
    @Autowired
    var movieFinder: MovieFinder? = null
    // ...
}

Вы также можете использовать @Autowired для интерфейсов, которые являются известными разрешаемыми зависимостями: BeanFactory, ApplicationContext, Environment, ResourceLoader, ApplicationEventPublisher и MessageSource. Эти интерфейсы и их расширенные интерфейсы, такие как ConfigurableApplicationContext или ResourcePatternResolver, разрешаются автоматически, без необходимости специальной настройки. В следующем примере выполняется автоматический поиск и связывание объекта ApplicationContext:

Java
public class MovieRecommender {
    @Autowired
    private ApplicationContext context;
    public MovieRecommender() {
    }
    // ...
}
Kotlin
class MovieRecommender {
    @Autowired
    lateinit var context: ApplicationContext
    // ...
}

Аннотации @Autowired, @Inject, @Value и @Resource обрабатываются реализациями BeanPostProcessor в Spring. Это означает, что невозможно применять эти аннотации внутри ваших собственных типов BeanPostProcessor или BeanFactoryPostProcessor (если таковые имеются). Эти типы должны быть "связаны" явным образом с помощью XML или метода @Bean в Spring.