TL; DR
Аннотация @Autowired избавляет вас от необходимости самостоятельно выполнять разводку в файле XML (или любым другим способом) и просто находит для вас, что нужно вводить, куда и делает это для вас.
Полное объяснение
@Autowired
Аннотаций позволяет пропускать конфигурации в другом месте , что вводить и просто делает это для вас. Предполагая, что ваш пакет - com.mycompany.movies
вы должны поместить этот тег в ваш XML (файл контекста приложения):
<context:component-scan base-package="com.mycompany.movies" />
Этот тег выполнит автоматическое сканирование. Предполагая, что каждый класс, который должен стать компонентом, помечается правильной аннотацией, например @Component
(для простого компонента) или @Controller
(для элемента управления сервлета) или @Repository
(для DAO
классов), и эти классы находятся где-то в пакете com.mycompany.movies
, Spring найдет все это и создаст боб для каждого. Это делается в 2 сканированиях классов - в первый раз он просто ищет классы, которые должны стать бином, и отображает инъекции, которые он должен делать, а во втором сканировании он вводит бины. Конечно, вы можете определить ваши bean-компоненты в более традиционном XML-файле или с помощью класса @Configuration (или любой их комбинации).
@Autowired
Аннотаций сообщает Spring , где инъекции должно произойти. Если вы помещаете его в метод, setMovieFinder
он понимает (по префиксу set
+ @Autowired
аннотации), что бин должен быть введен. Во втором сканировании Spring ищет bean-компонент типа MovieFinder
, и если он находит такой bean-компонент, он внедряет его в этот метод. Если он найдет два таких боба, вы получите Exception
. Чтобы избежать этого Exception
, вы можете использовать @Qualifier
аннотацию и сообщить ей, какой из двух bean-компонентов нужно внедрить, следующим образом:
@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;
}
@Resource
(Вы можете прочитать некоторые дополнительные данные о нем в первый комментарий на этот ответ) избавляет вас использование двух аннотаций и вместо того, чтобы использовать только один.
Я просто добавлю еще два комментария:
- Хорошей практикой будет использование
@Inject
вместо того, @Autowired
потому что это не зависит от Spring и является частью JSR-330
стандарта .
- Еще одна хорошая практика - помещать
@Inject
/ @Autowired
на конструктор вместо метода. Если вы поместите его в конструктор, вы можете проверить, что введенные bean-компоненты не равны NULL и быстро перестают работать, когда вы пытаетесь запустить приложение и избегать того, NullPointerException
когда вам действительно нужно использовать bean-компонент.
Обновление : чтобы завершить картину, я создал новый вопрос о @Configuration
классе.
MovieFinder
это интерфейс, и у нас есть компонент дляMovieFinderImpl
(bean id = movieFinder), Spring автоматически внедрит его по типу или по имени?@Qualifier
. Если вы делаете - по имени, если нет - по типу. По типу будет работать, только если у вас есть только один тип компонентаMovieFinder
в вашем контексте. Более 1 приведет к исключению.@Autowired
работает аннотация кprepare
методу в Примере 2 . Это инициализация,MovieRecommender
но, технически, это НЕ сеттер.@Autowired
также работает для конструкторов. Он находит необходимые зависимости и вставляет их в конструктор.Ничто в примере не говорит о том, что «классы реализуют один и тот же интерфейс».
MovieCatalog
это тип, аCustomerPreferenceDao
другой тип. Весна может легко отличить их.В Spring 2.x проводка bean-компонентов в основном происходила через идентификаторы или имена bean-компонентов. Это все еще поддерживается в Spring 3.x, но часто у вас будет один экземпляр компонента с определенным типом - большинство сервисов являются синглетонами. Создание названий для них утомительно. Поэтому Spring начал поддерживать «autowire по типу».
Примеры показывают различные способы, которыми вы можете использовать для внедрения bean-компонентов в поля, методы и конструкторы.
XML уже содержит всю информацию, которая нужна Spring, поскольку вы должны указать полное имя класса в каждом бине. Вы должны быть немного осторожнее с интерфейсами, хотя:
Эта автопроводка потерпит неудачу:
Поскольку Java не хранит имена параметров в байт-коде, Spring больше не может различать два bean-компонента. Исправление заключается в использовании
@Qualifier
:источник
prepare
, какие параметры будут использоваться для вызова этой функции?@Autowired
поля вводятся. Затем Spring увидит, что параметры необходимы, и будет использовать те же правила, что и для ввода полей, чтобы найти параметры.Да, вы можете настроить XML-файл контекста сервлета Spring для определения ваших bean-компонентов (т. Е. Классов), чтобы он мог выполнять автоматическое внедрение для вас. Тем не менее, обратите внимание, что вам нужно выполнить другие конфигурации, чтобы запустить Spring и запустить его, и лучший способ сделать это - пройти курс обучения.
После того, как вы, вероятно, настроили свой Spring, вы можете сделать следующее в своем xml-файле контекста Spring для примера 1, приведенного выше, (пожалуйста, замените имя пакета com.movies на истинное имя пакета, и если это сторонняя версия class, затем убедитесь, что соответствующий файл jar находится в пути к классам):
или если класс MovieFinder имеет конструктор с примитивным значением, то вы могли бы что-то вроде этого,
или если класс MovieFinder имеет конструктор, ожидающий другой класс, то вы можете сделать что-то вроде этого,
... где « otherBeanRef » - это другой компонент, имеющий ссылку на ожидаемый класс.
источник
@Autowired