Руководство по весне @Autowired
1. обзор
Начиная с Spring 2.5, фреймворк представил новый стиль внедрения зависимостей, основанный на аннотациях@Autowired. Эта аннотация позволяет Spring разрешать и вводить взаимодействующие bean-компоненты в ваш bean-компонент.
В этом руководстве мы рассмотрим, как включить автоматическое подключение, различных аннотаций ways to wire in beans,_ making beans optional, resolving bean conflicts using _@Qualifier, а также возможные сценарии исключения.
Дальнейшее чтение:
Сканирование пружинных компонентов
Узнайте о механизме сканирования компонентов Spring и о том, как настроить его под свои нужды
Введение в инверсию управления и инжекцию зависимостей с помощью пружины
Краткое введение в концепции инверсии управления и внедрения зависимостей с последующей простой демонстрацией с использованием Spring Framework
2. Включение аннотаций@Autowired
Если вы используете в своем приложении конфигурацию на основе Java, вы можете включить инъекцию, управляемую аннотациями, используяAnnotationConfigApplicationContext для загрузки конфигурации Spring, как показано ниже:
@Configuration
@ComponentScan("com.example.autowire.sample")
public class AppConfig {}
В качестве альтернативы в Spring XML его можно включить, объявив его в файлах Spring XML следующим образом:<context:annotation-config/>
3. Используя@Autowired
Как только добавление аннотаций включено, автоматическое подключение можно использовать для свойств, сеттеров и конструкторов.
3.1. @Autowired в свойствах
Аннотация может использоваться непосредственно в свойствах, поэтому устраняется необходимость в методах получения и установки:
@Component("fooFormatter")
public class FooFormatter {
public String format() {
return "foo";
}
}
@Component
public class FooService {
@Autowired
private FooFormatter fooFormatter;
}
В приведенном выше примере Spring ищет и вводитfooFormatter при созданииFooService.
3.2. @Autowired на сеттерах
Аннотация@Autowired может использоваться в методах установки. В приведенном ниже примере, когда аннотация используется в методе установки, метод установки вызывается с экземпляромFooFormatter при созданииFooService:
public class FooService {
private FooFormatter fooFormatter;
@Autowired
public void setFooFormatter(FooFormatter fooFormatter) {
this.fooFormatter = fooFormatter;
}
}
3.3. @Autowired в конструкторах
Аннотация@Autowired также может использоваться для конструкторов. В приведенном ниже примере, когда аннотация используется в конструкторе, экземплярFooFormatter вводится в качестве аргумента в конструктор при созданииFooService:
public class FooService {
private FooFormatter fooFormatter;
@Autowired
public FooService(FooFormatter fooFormatter) {
this.fooFormatter = fooFormatter;
}
}
4. @Autowired и дополнительные зависимости
Spring ожидает, что зависимости@Autowired будут доступны при создании зависимого bean-компонента. Если платформа не может разрешить bean-компонент для проводки, она выдаст исключение, указанное ниже, и не позволит контейнеру 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 по типу. Если в контейнере доступно более одного bean-компонента одного и того же типа, среда выдаст фатальное исключение, указывающее, что для автопроводки доступно более одного bean-компонента.
5.1. Автоподключение по@Qualifier
Аннотацию@Qualifier можно использовать для подсказки и сужения необходимого bean-компонента:
@Component("fooFormatter")
public class FooFormatter implements Formatter {
public String format() {
return "foo";
}
}
@Component("barFormatter")
public class BarFormatter implements Formatter {
public String format() {
return "bar";
}
}
public class FooService {
@Autowired
private Formatter formatter;
}
Поскольку существует две конкретные реализацииFormatter, доступные для инъекции контейнера Spring, Spring выдаст исключениеNoUniqueBeanDefinitionException при построенииFooService: __
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
Этого можно избежать, сузив реализацию с помощью аннотации@Qualifier:
public class FooService {
@Autowired
@Qualifier("fooFormatter")
private Formatter formatter;
}
Указав@Qualifier с именем конкретной реализации, в данном случае какfooFormatter, мы можем избежать двусмысленности, когда Spring находит несколько bean-компонентов одного типа.
Обратите внимание, что значение аннотации@Qualifier совпадает с именем, объявленным в аннотации@Component нашей реализацииFooFormatter.
5.2. Автоматическое подключение по специальному классификатору
Spring позволяет нам создавать нашу собственную аннотацию@Qualifier. Чтобы создать настраиваемый квалификатор, определите аннотацию и предоставьте аннотацию@Qualifier в определении, как показано ниже:
@Qualifier
@Target({
ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface FormatterType {
String value();
}
После определенияFormatterType можно использовать в различных реализациях для указания пользовательского значения:
@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";
}
}
После того, как реализации аннотированы, пользовательская аннотация Qualifier может использоваться следующим образом:
@Component
public class FooService {
@Autowired
@FormatterType("Foo")
private Formatter formatter;
}
Значение, указанное в аннотации@Target, ограничивает, где квалификатор может использоваться для отметки точек инъекции.
В приведенном выше фрагменте кода квалификатор можно использовать для устранения неоднозначности точки, в которой Spring может внедрить компонент в поле, метод, тип и параметр.
5.3. Автоподключение по имени
В качестве запасного варианта Spring использует имя компонента в качестве значения квалификатора по умолчанию.
Итак, определяя имя свойства bean-компонента, в данном случаеfooFormatter, Spring сопоставляет его с реализациейFooFormatter и вводит эту конкретную реализацию при построенииFooService:
public class FooService {
@Autowired
private Formatter fooFormatter;
}
6. Заключение
Хотя как@Qualifier, так и резервное соответствие имени bean-компонента можно использовать для сужения до определенного bean-компонента, на самом деле автоматическое подключение - это внедрение по типу, и это лучший способ использовать эту функцию контейнера.
Исходный код этого руководства находится вthe GitHub project - это проект на основе Eclipse, поэтому его будет легко импортировать и запускать как есть.