Понимание использования Spring @Autowired
Я читаю справочную документацию весны 3.0.x, чтобы понять аннотацию Spring Autowired:
3.9.2 @Autowired и @Inject
Я не могу понять приведенные ниже примеры. Нужно ли нам что-то делать в XML, чтобы он работал?
- Не удалось импортировать новый проект Gradle: не удалось найти версию Build Tools * .0.0
- Как включить Spongy Castle JAR в Android?
- Как создать classы Java из файла WSDL
- Возможна ли сумма ArrayList без цикла
- Java - чтение файла и разбиение на несколько файлов
ПРИМЕР 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а для реализации одного и того же интерфейса и использования одного и того же classа?
Пример:
class Red implements Color class Blue implements Color class myMainClass{ @Autowired private Color color; draw(){ color.design(); } }
Какой метод проектирования будет называться? Как я могу убедиться, что метод проектирования classа Red будет вызываться, а не Blue?
- Отправить текст через Bluetooth от Java Server до Android Client
- Android - обновить контакт
- При создании службы нет пустого конструктора
- Удалить дубликаты из ArrayLists
- Использование serviceloader на android
- Поиск второго по величине числа в массиве
- warning: путь к bootstrap, не установленный вместе с -source 1.5
- Драйвер не смог установить безопасное соединение с SQL Server с использованием шифрования Secure Sockets Layer (SSL)
@Autowired
аннотация позволяет пропустить конфигурации в другом месте, что нужно вводить, и просто делает это для вас. Предполагая, что ваш пакет com.mycompany.movies
вы должны поместить этот тег в свой XML-файл (контекстный файл приложения):
Этот тег будет выполнять автоматическое сканирование. Предполагая, что каждый class, который должен стать bean-компонентом, аннотируется с помощью правильной annotations, такой как @Component
(для простого компонента) или @Controller
(для управления сервлетом) или @Repository
(для classов DAO
), и эти classы находятся где-то под пакетом com.mycompany.movies
, Spring найдет все это и создаст компонент для каждого из них. Это делается при 2-х проверках classов – в первый раз, когда он просто ищет classы, которые должны стать компонентом, и отображает инъекции, которые он должен выполнять, а на втором сканировании он вводит компоненты. Конечно, вы можете определить свои компоненты в более традиционном XML-файле или в classе @Configuration (или любой комбинации из трех).
@Autowired
сообщает Spring, где должна произойти инъекция. Если вы положили его на метод setMovieFinder
он понимает (по set
префикса + @Autowired
annotation), что необходимо @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, это выглядит примерно так:
В объявлении @Autowired
вам нужно также добавить @Qualifier
чтобы указать, какая из двух цветовых @Qualifier
для инъекции:
@Autowired @Qualifier("redBean") public void setColor(Color color) { this.color = color; }
Если вы не хотите использовать две annotations ( @Autowired
и @Qualifier
), вы можете использовать @Resource
для объединения этих двух:
@Resource(name="redBean") public void setColor(Color color) { this.color = color; }
@Resource
(вы можете прочитать некоторые дополнительные данные об этом в первом комментарии к этому ответу) избавляет вас от использования двух аннотаций, и вместо этого вы используете только один.
Я просто добавлю еще два комментария:
- Хорошей практикой было бы использовать
@Inject
вместо@Autowired
потому что он не зависит от Spring и является частью стандартаJSR-330
. - Другой хорошей практикой было бы поставить
@Inject
/@Autowired
на конструктор вместо метода. Если вы поместите его в конструктор, вы можете проверить, что введенные bean-компоненты не являются нулевыми и не работают быстро, когда вы пытаетесь запустить приложение и избегаете исключенияNullPointerException
когда вам нужно фактически использовать компонент.
Итак, @Autowired
итог: @Autowired
annotation избавляет вас от необходимости @Autowired
проводку самостоятельно в XML-файле (или любым другим способом) и просто находит для вас то, что нужно вводить туда и делает это для вас.
Обновление . Чтобы завершить изображение, я создал новый вопрос о classе @Configuration
.
Ничто в этом примере не говорит о том, что «classы реализуют один и тот же интерфейс». MovieCatalog
– это тип, а CustomerPreferenceDao
– другой тип. Весна может легко рассказать им обособленно.
Весной 2.x проводка бобов в основном происходила с помощью идентификаторов или имен bean-компонентов. Это все еще поддерживается Spring 3.x, но часто у вас будет один экземпляр компонента с определенным типом – большинство сервисов – это одиночные. Создание имен для них утомительно. Поэтому Spring начала поддерживать «autwire by type».
То, что показывают примеры, – это различные способы, которыми вы можете использовать для добавления компонентов в поля, методы и конструкторы.
XML уже содержит всю информацию, необходимую Spring, поскольку вам нужно указать полное имя classа в каждом компоненте. Вы должны быть немного осторожны с интерфейсами, хотя:
Это автоподключение не удастся:
@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, чтобы определить ваши компоненты (то есть classы), чтобы он мог выполнять автоматическую инъекцию для вас. Однако имейте в виду, что вам нужно делать другие конфигурации, чтобы запустить Spring и работать, и лучший способ сделать это – следовать руководству.
Как только у вас настроена настройка Spring, вы можете сделать следующее в вашем XML-файле контекста Spring сервлета для примера 1 выше, чтобы работать (пожалуйста, замените имя пакета com.movies на то, что истинное имя пакета, и если это сторонний участник class, то убедитесь, что соответствующий файл jar находится в пути к classам):
или если class MovieFinder имеет конструктор с примитивным значением, то вы могли бы что-то вроде этого,
или если class MovieFinder имеет конструктор, ожидающий другого classа, то вы можете сделать что-то вроде этого,
… где « otherBeanRef » – это еще один компонент, который имеет ссылку на ожидаемый class.
@Autowired
Пусть Spring автоматически подключит другие бобы к вашим classам с помощью @Autowired annotations.
@Service public class CompanyServiceImpl implements CompanyService { @Autowired private CompanyDAO companyDAO; ... }
Spring Annotation Tip Весенние бобы могут быть связаны по имени или по типу. @Autowire по умолчанию является инъекцией типа. @Qualifier spring annotation может использоваться для дальнейшей тонкой настройки автоустановки. Аннотацию @Resource (javax.annotation.Resource) можно использовать для проводки по имени. Бобы, которые сами определяются как тип коллекции или карты, не могут быть введены через @Autowired, поскольку сопоставление типов не подходит для них. Используйте @Resource для таких компонентов, ссылаясь на конкретную коллекцию или картографический компонент по уникальному имени