1. Обзор
Начиная с Spring 2.5, в фреймворке были введены управляемые аннотациями Инъекции зависимостей . Основная аннотация этой функции – @Autowired . Это позволяет Spring разрешать и вводить сотрудничающие бобы в наш боб.
Дальнейшее чтение:
Сканирование пружинных Компонентов
Введение в инверсию управления и внедрение зависимостей с помощью пружины
В этом уроке мы сначала рассмотрим, как включить автоматическое подключение и различные | способы автоматического подключения компонентов. Позже мы поговорим о разрешении конфликтов компонентов с использованием @квалификатора аннотации, , а также о возможных сценариях исключений.
2. Включение аннотаций @Autowired
Платформа Spring позволяет автоматически внедрять зависимости. Другими словами, объявив все зависимости компонентов в файле конфигурации Spring, контейнер Spring может автоматически устанавливать связи между сотрудничающими компонентами . Это называется Автопроводка Spring bean .
Чтобы использовать конфигурацию на основе Java в нашем приложении, давайте включим инъекцию на основе аннотаций для загрузки нашей конфигурации Spring:
@Configuration @ComponentScan("com.baeldung.autowire.sample") public class AppConfig {}
В качестве альтернативы, аннотация <контекст:аннотация-конфигурация> в основном используется для активации аннотаций внедрения зависимостей в XML-файлах Spring.
Кроме того, Spring Boot вводит @SpringBootApplication аннотацию . Эта единственная аннотация эквивалентна использованию @Configuration , @EnableAutoConfiguration и @ComponentScan .
Давайте использовать эту аннотацию в основном классе приложения:
@SpringBootApplication class VehicleFactoryApplication { public static void main(String[] args) { SpringApplication.run(VehicleFactoryApplication.class, args); } }
В результате, когда мы запускаем это приложение Spring Boot, оно автоматически сканирует компоненты в текущем пакете и его подпакетах . Таким образом, он зарегистрирует их в контексте приложения Spring и позволит нам вводить компоненты с помощью @Autowired .
3. Использование @Autowired
После включения внедрения аннотаций мы можем использовать автоматическое подключение к свойствам, установщикам и конструкторам .
3.1. @Автоматически подключается к свойствам
Давайте посмотрим, как мы можем аннотировать свойство с помощью @Autowired . Это устраняет необходимость в геттерах и сеттерах.
Во-первых, давайте определим FooFormatter bean:
@Component("fooFormatter") public class FooFormatter { public String format() { return "foo"; } }
Затем мы введем эту фасоль в Службу питания фасоль, используя @Autowired об определении поля:
@Component public class FooService { @Autowired private FooFormatter fooFormatter; }
В результате Spring вводит FooFormatter при создании Службы питания .
3.2. @Автоматическое подключение к сеттерам
Теперь давайте попробуем добавить @Autowired аннотация метода настройки.
В следующем примере метод setter вызывается с экземпляром FooFormatter при создании Службы питания :
public class FooService { private FooFormatter fooFormatter; @Autowired public void setFooFormatter(FooFormatter fooFormatter) { this.fooFormatter = fooFormatter; } }
3.3. @Автоматически подключается к конструкторам
Наконец, давайте используем @Autowired в конструкторе.
Мы увидим, что экземпляр FooFormatter вводится Spring в качестве аргумента конструктора Foodservice :
public class FooService { private FooFormatter fooFormatter; @Autowired public FooService(FooFormatter fooFormatter) { this.fooFormatter = fooFormatter; } }
4. @Автоматические и необязательные зависимости
При создании компонента должны быть доступны зависимости @Autowired . В противном случае если Spring не сможет разрешить компонент для подключения, он выдаст исключение .
Следовательно, это предотвращает успешный запуск контейнера Spring, за исключением формы:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.autowire.sample.FooDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
Чтобы исправить это, нам нужно объявить компонент требуемого типа:
public class FooService { @Autowired(required = false) private FooDAO dataAccessor; }
5. Автоматическое Устранение неоднозначности
По умолчанию Spring разрешает @Autowired записи по типу. Если в контейнере доступно более одного компонента одного и того же типа, фреймворк выдаст фатальное исключение .
Чтобы разрешить этот конфликт, нам нужно явно указать Spring, какой компонент мы хотим ввести.
5.1. Автоматическое подключение с помощью @квалификатора
Например, давайте посмотрим, как мы можем использовать аннотацию @Qualifier для указания требуемого компонента.
Сначала мы определим 2 компонента типа Форматер :
@Component("fooFormatter") public class FooFormatter implements Formatter { public String format() { return "foo"; } }
@Component("barFormatter") public class BarFormatter implements Formatter { public String format() { return "bar"; } }
Теперь давайте попробуем внедрить компонент Форматирования в класс FooService :
public class FooService { @Autowired private Formatter formatter; }
В нашем примере для контейнера Spring доступны две конкретные реализации Форматирования . В результате Spring выдаст исключение NoUniqueBeanDefinitionException исключение при создании Foodservice :
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.autowire.sample.Formatter] is defined: expected single matching bean but found 2: barFormatter,fooFormatter
Мы можем избежать этого, сузив реализацию с помощью @Квалификатор аннотация:
public class FooService { @Autowired @Qualifier("fooFormatter") private Formatter formatter; }
Когда существует несколько компонентов одного и того же типа, рекомендуется использовать @Квалификатор , чтобы избежать двусмысленности.
Пожалуйста, обратите внимание, что значение @Квалификатора аннотации совпадает с именем, объявленным в @Компоненте аннотации нашей FooFormatter реализации.
5.2. Автоматическое подключение с помощью Пользовательского классификатора
Spring также позволяет нам создавать свой собственный @классификатор аннотацию . Для этого мы должны предоставить @Квалификатор аннотацию с определением:
@Qualifier @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface FormatterType { String value(); }
Затем мы можем использовать тип форматирования в различных реализациях для указания пользовательского значения:
@FormatterType("Foo") @Component public class FooFormatter implements Formatter { public String format() { return "foo"; } }
@FormatterType("Bar") @Component public class BarFormatter implements Formatter { public String format() { return "bar"; } }
Наконец, наша пользовательская аннотация квалификатора готова к использованию для автоматической проводки:
@Component public class FooService { @Autowired @FormatterType("Foo") private Formatter formatter; }
Значение, указанное в @Target мета-аннотации, ограничивает применение квалификатора, которым в нашем примере являются поля, методы, типы и параметры.
5.3. Автоматическое подключение по имени
Spring использует имя компонента в качестве значения квалификатора по умолчанию. Он проверит контейнер и будет искать компонент с точным именем в качестве свойства для его автоматического подключения.
Следовательно, в нашем примере Spring сопоставляет имя свойства FooFormatter с реализацией FooFormatter . Поэтому он вводит эту конкретную реализацию при создании Foodservice :
public class FooService { @Autowired private Formatter fooFormatter; }
6. Заключение
В этой статье мы обсудили автопроводку и различные способы ее использования. Мы также рассмотрели способы решения двух распространенных исключений автоматической проводки, вызванных либо отсутствующим компонентом, либо неоднозначной инъекцией компонента.
Исходный код этой статьи доступен на проекте GitHub .