Руководство по весне @Autowired

Руководство по весне @Autowired

1. обзор

Начиная с Spring 2.5, фреймворк представил новый стиль внедрения зависимостей, основанный на аннотациях@Autowired. Эта аннотация позволяет Spring разрешать и вводить взаимодействующие bean-компоненты в ваш bean-компонент.

В этом руководстве мы рассмотрим, как включить автоматическое подключение, различных аннотаций ways to wire in beans,_ making beans optional, resolving bean conflicts using _@Qualifier, а также возможные сценарии исключения.

Дальнейшее чтение:

Сканирование пружинных компонентов

Узнайте о механизме сканирования компонентов Spring и о том, как настроить его под свои нужды

Read more

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

Краткое введение в концепции инверсии управления и внедрения зависимостей с последующей простой демонстрацией с использованием Spring Framework

Read more

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, поэтому его будет легко импортировать и запускать как есть.