Понимание использования Spring @Autowired



Я читаю spring 3.0.X справочная документация для понимания Spring Autowired аннотация:



3.9.2 @Autowired и @Inject



Я не могу понять приведенные ниже примеры. Нужно ли что-то делать в XML, чтобы он работал?



Пример 1



public class SimpleMovieLister {

private MovieFinder movieFinder;

@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}

// ...
}


Пример 2



public class MovieRecommender {

private MovieCatalog movieCatalog;

private CustomerPreferenceDao customerPreferenceDao;

@Autowired
public void prepare(MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}

// ...
}


как два класса могут быть автоматически подключены, реализуя один и тот же интерфейс и используя один и тот же класс?



пример:



class Red implements Color
class Blue implements Color

class myMainClass{
@Autowired
private Color color;

draw(){
color.design();
}
}


какой метод проектирования будет вызван? Как я могу убедиться, что метод проектирования Красного класса будет вызван, а не синий?

809   4  

4 ответов:

TL; DR

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

полное описание

The @Autowired аннотация позволяет пропустить конфигурации в другом месте того, что нужно вводить, и просто делает это за вас. Предполагая, что ваш пакет com.mycompany.movies вы должны поместить этот тег в свой XML (файл контекста приложения):

<context:component-scan base-package="com.mycompany.movies" />

этот тег будет выполнять автоматическое сканирование. Предполагая, что каждый класс, который должен стать Бобом, аннотируется правильной аннотацией, такой как @Component (для простого боба) или @Controller (для управления сервлетом) или @Repository (для DAO классы) и эти классы находятся где-то под пакетом com.mycompany.movies, Весна найдет все это и создаст боб для каждого из них. Это делается в 2 сканирования классов - в первый раз он просто ищет классы, которые нужно чтобы стать Бобом и сопоставить инъекции, которые он должен делать, и на втором сканировании он вводит бобы. Конечно, вы можете определить свои бобы в файл XML или @настройки класс (или любая комбинация из трех).

The @Autowired аннотация говорит источник, где нужны инъекции, чтобы произойти. Если вы ставите его на метод setMovieFinder он понимает (по префиксу set + the @Autowired аннотации), что Боб должен быть введен. В второе сканирование, Spring ищет Боб типа MovieFinder, и если он находит такой Боб, он вводит его в этот метод. Если он найдет два таких Боба, вы получите Exception. Чтобы избежать Exception можно использовать @Qualifier аннотация и скажите ему, какой из двух бобов ввести следующим образом:

@Qualifier("redBean")
class Red implements Color {
   // Class code here
}

@Qualifier("blueBean")
class Blue implements Color {
   // Class code here
}

или если вы предпочитаете объявлять бобы в своем XML, это будет выглядеть примерно так:

<bean id="redBean" class="com.mycompany.movies.Red"/>

<bean id="blueBean" class="com.mycompany.movies.Blue"/>

на @Autowired объявление, Вам нужно также добавить @Qualifier чтобы сказать, какой из двух цветных бобов вводить:

@Autowired
@Qualifier("redBean")
public void setColor(Color color) {
  this.color = color;
}

если вы не хотите использовать две аннотации (на @Autowired и @Qualifier) можно использовать @Resource чтобы объединить эти два:

@Resource(name="redBean")
public void setColor(Color color) {
  this.color = color;
}

The @Resource (вы можете прочитать некоторые дополнительные данные об этом в первом комментарии к этому ответу) избавляет вас от использования двух аннотаций, а вместо этого вы используете только один.

я просто добавлю еще два комментария:

  1. хорошей практикой было бы использовать @Inject вместо @Autowired потому что он не является специфичным для весны и часть JSR-330 стандартный.
  2. другой хорошей практикой было бы поставить @Inject/@Autowired на конструкторе вместо метода. Если вы поместите его в конструктор, вы можете проверить, что введенные бобы не являются нулевыми и быстро завершаются неудачей при попытке запустить приложение и избежать NullPointerException когда вам нужно на самом деле использовать Боб.

обновление: To завершите картину, я создал новому вопросу о @Configuration класса.

ничто в Примере не говорит о том, что "классы реализуют один и тот же интерфейс". MovieCatalog тип и CustomerPreferenceDao - это другой тип. Весна может легко отличить их друг от друга.

Весной 2.x, проводка бобов в основном происходила через идентификаторы или имена бобов. Это все еще поддерживается весной 3.x но часто у вас будет один экземпляр боба с определенным типом - большинство сервисов являются синглетами. Создание имен для них утомительно. Так весна начала поддерживать "autowire by тип."

что показывают примеры, это различные способы, которые вы можете использовать для ввода бобов в поля, методы и конструкторы.

XML уже содержит всю информацию, которая нужна Spring, так как вы должны указать полное имя класса в каждом компоненте. Вы должны быть немного осторожны с интерфейсами, хотя:

эта автопроводка выйдет из строя:

 @Autowired
 public void prepare( Interface1 bean1, Interface1 bean2 ) { ... }

поскольку Java не сохраняет имена параметров в байтовом коде, Spring не может различать между двумя бобами больше нет. Исправление заключается в использовании @Qualifier:

 @Autowired
 public void prepare( @Qualifier("bean1") Interface1 bean1,
     @Qualifier("bean2")  Interface1 bean2 ) { ... }

Да, вы можете настроить XML-файл контекста сервлета Spring для определения ваших бобов (т. е. классов), чтобы он мог выполнять автоматическую инъекцию для вас. Однако обратите внимание, что вам нужно сделать другие конфигурации, чтобы иметь Spring up и running, и лучший способ сделать это-следовать учебнику ground up.

после того, как вы настроили Spring вероятно, вы можете сделать следующее в своем XML-файле контекста Spring servlet например 1 выше для работы (пожалуйста заменить имя пакета com.кино к тому, что такое истинное имя пакета, и если это 3-й класс, то убедитесь, что соответствующий файл jar находится на пути к классу):

<beans:bean id="movieFinder" class="com.movies.MovieFinder" />

или если класс MovieFinder имеет конструктор с примитивным значением, то вы могли бы что-то вроде этого,

<beans:bean id="movieFinder" class="com.movies.MovieFinder" >
    <beans:constructor-arg value="100" />
</beans:bean>

или если класс MovieFinder имеет конструктор, ожидающий другого класса, то вы можете сделать что-то вроде это

<beans:bean id="movieFinder" class="com.movies.MovieFinder" >
    <beans:constructor-arg ref="otherBeanRef" />
</beans:bean>

...где ' otherBeanRef ' - это еще один компонент, который имеет ссылку на ожидаемый класс.

@Autowired

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

@Service
public class CompanyServiceImpl implements CompanyService {

    @Autowired
    private CompanyDAO companyDAO;

    ...
}

Весенняя Аннотация наконечник весенние бобы могут быть подключены по имени или по типу. @Autowire по умолчанию-это инъекция, управляемая типом. Аннотация @ Qualifier spring может быть использована для дальнейшей тонкой настройки автопроводки. @ Resource (javax.аннотация.Ресурс) аннотацию можно использовать для проводки по имени. Бобы, которые сами определены как коллекция или тип карты, не могут быть вводится через @Autowired, потому что сопоставление типов не применимо к ним должным образом. Используйте @Resource для таких бобов, ссылаясь на конкретную коллекцию или боб карты по уникальному имени

Comments

    Ничего не найдено.