Spring реализует автоматическую сборку с двух точек зрения:
- Сканирование компонентов: Spring автоматически обнаруживает bean-компоненты, которые необходимо создать в контексте приложения.
- Autowiring: Spring автоматически удовлетворяет зависимости между bean-компонентами.
Чтобы более наглядно объяснить сканирование компонентов и автоматическую сборку, давайте возьмем пример звуковой системы, которая в основном включает в себя следующее:
- CD-интерфейс
- Класс реализации интерфейса CD
- CD-плеер
Объяснение отношений между компакт-дисками и проигрывателями компакт-дисков:
Если вы не вставляете (не вставляете) компакт-диск в проигрыватель компакт-дисков, проигрыватель компакт-дисков на самом деле бесполезен. Итак, так сказать,
Проигрыватели компакт-дисков полагаются на компакт-диски в своей работе.
1. Создайте обнаруживаемые bean-компоненты
Сначала создайте интерфейс компакт-диска CompactDisc:
package chapter02;
public interface CompactDisc {
void play();
}
Затем создайте класс реализации SgtPeppers интерфейса CD:
package chapter02;
import org.springframework.stereotype.Component;
@Component
public class SgtPeppers implements CompactDisc {
@Override
public void play() {
String title = "Sgt.Pepper's Lonely Hearts Club Band";
String artists = "The Beatles";
System.out.println("Playing " + title + " By " + artists);
}
}
Отличие класса SgtPeppers от предыдущего класса в том, что он использует@Component
аннотация.
Эта аннотация указывает, что класс будет действовать как класс компонента, и сообщает Spring о создании bean-компонентов для этого класса.
Итак, как мне заставить Spring обнаружить его и создать bean-компонент?
Однако в настоящее время требуется сканирование компонентов.В Spring сканирование компонентов по умолчанию не включено..
Поэтому нам нужно явно настроить Spring, чтобы указать ему искать классы, аннотированные с помощью @Component, и создавать для них bean-компоненты.
Создайте класс CDPLAYERCONFIG:
package chapter02;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan
public class CDPlayerConfig {
}
Отличие этого класса от предыдущего в том, что он использует@ComponentScan
Аннотация, которая позволяет Spring включить сканирование компонентов.
По умолчанию @ComponentScan сканирует тот же пакет, что и класс конфигурации, и все подпакеты в этом пакете, ища классы, аннотированные @Component.
2. Проверьте сканирование компонентов
Чтобы проверить, может ли Spring обнаружить созданный bean-компонент, мы создаем простой тест JUnit.Чтобы выполнить этот тест, нам нужно импортировать следующие два пакета jar:
- hamcrest-core-2.1.jar
- junit-4.12.jar
Способ импорта пакета jar выглядит следующим образом:
Схема структуры проекта после завершения импорта выглядит следующим образом:
package chapter02;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
@Autowired
private CompactDisc compactDisc;
@Test
public void cdShouldNotBeNull() {
assertNotNull(compactDisc);
compactDisc.play();
}
}
Простое объяснение кода:
@RunWith(SpringJUnit4ClassRunner.class)
, который автоматически создаст контекст приложения Spring при запуске теста.
@ContextConfiguration(classes = CDPlayerConfig.class)
сообщит Spring, что конфигурацию необходимо загрузить в CDPlayerConfig.
Полевой компактДиск на@Autowired
Аннотация будет внедрять bean-компонент SgtPeppers в поле compactDisc, потому что это класс реализации интерфейса CompactDisc и добавляет@Component
аннотация.
Запустите тестовый метод cdShouldNotBeNull, и вы обнаружите, что тест проходит успешно, а compactDisc не равен нулю:
3. Установите идентификатор компонента
Всем bean-компонентам в контексте приложения Spring присваивается идентификатор,По умолчанию Spring первая буква имени класса будет строчной в качестве идентификатора компонента..
Например, идентификатор bean-компонента SgtPeppers в приведенном выше коде — sgtPeppers.
Есть два способа установить идентификатор компонента:
3.1 Используйте @Component для установки идентификатора компонента
@Component("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc {
......
}
3.2 Используйте @Named для установки идентификатора компонента
Аннотация @Named — это не аннотация фреймворка Spring, а аннотация в спецификации внедрения зависимостей Java (Java Dependency Injection), поэтому вам необходимо импортировать пакет jar: javax.inject-1.jar, вы можете обратиться к способ импортировать пакет jarНачало работы с Spring (1): Создание проекта Spring.
import javax.inject.Named;
@Named("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc {
......
}
Рекомендуется использовать в проектах Spring@Component
аннотация.
4. Установите базовый пакет для сканирования компонентов
По умолчанию,@ComponentScan
Аннотация сканирует компонент, используя пакет, в котором класс конфигурации находится в качестве базового пакета.
Но иногда мы помещаем класс конфигурации в отдельный пакет, чтобы отделить его от остального кода приложения.
В этом сценарии базовый пакет по умолчанию не соответствует требованиям.
@ComponentScan
Аннотация поддерживает передачу в указанном базовом пакете, возможны следующие сценарии:
4.1 Укажите базовый пакет для сканирования (одиночный)
@ComponentScan("chapter02")
public class CDPlayerConfig {
}
или:
@ComponentScan(basePackages = "chapter02")
public class CDPlayerConfig {
}
4.2 Укажите базовые пакеты для сканирования
@ComponentScan(basePackages = {"chapter01", "chapter02"})
public class CDPlayerConfig {
}
4.3 Указание базовых пакетов для сканирования (типовая безопасность)
@ComponentScan(basePackageClasses = {CDPlayer.class})
public class CDPlayerConfig {
}
basePackageClasses также поддерживает указание нескольких классов, и пакет, в котором находится указанный класс, будет использоваться в качестве базового пакета для сканирования компонентов.
Рекомендуется использовать этот типобезопасный способ указать базовый пакет для сканирования.
5. Автомонтирование путем добавления аннотаций к bean-компонентам
Autowiring — это способ позволить Spring автоматически удовлетворять зависимости bean-компонентов.В процессе удовлетворения зависимостей он будет искать другие bean-компоненты, которые соответствуют потребностям bean-компонента в контексте приложения Spring.
Чтобы добиться автопроводки, вам нужно использовать Spring@Autowired
аннотация.
@Autowired
В общем, есть три способа его использования:
5.1 Использование конструктора
package chapter02;
public interface MediaPlayer {
void play();
}
package chapter02;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc compactDisc;
@Autowired
public CDPlayer(CompactDisc compactDisc) {
this.compactDisc = compactDisc;
}
@Override
public void play() {
compactDisc.play();
}
}
5.2 Использование методов установки свойств
package chapter02;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc compactDisc;
@Autowired
public void setCompactDisc(CompactDisc compactDisc) {
this.compactDisc = compactDisc;
}
@Override
public void play() {
compactDisc.play();
}
}
5.3 Использование любого метода класса
package chapter02;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc compactDisc;
@Autowired
public void insertDisc(CompactDisc compactDisc) {
this.compactDisc = compactDisc;
}
@Override
public void play() {
compactDisc.play();
}
}
Будь то конструктор, метод установки или другой метод, Spring попытается удовлетворить зависимости, объявленные в параметрах метода.
Если есть один и только один bean-компонент, который соответствует требованию зависимости, то этот bean-компонент будет подключен.
Если нет подходящего bean-компонента, Spring выдаст исключение при создании контекста приложения.
Этого исключения можно избежать, установив для свойства require значение false:
@Autowired(required = false)
public CDPlayer(CompactDisc compactDisc) {
this.compactDisc = compactDisc;
}
Тем не менее, рекомендуется использовать его с осторожностью, чтобы избежать обнаружения соответствия bean-компонента и исключения NullPointerException, когда код не проверен на нуль.
Если более чем один bean-компонент может удовлетворить зависимость, Spring выдаст исключение, указывающее, что явно не указано, какой bean-компонент выбрать для автоматического связывания.
Аннотацию @Autowired также можно заменить аннотацией @Inject (полученной из спецификации внедрения зависимостей Java), которая также включает автоматическое связывание:
package chapter02;
import org.springframework.stereotype.Component;
import javax.inject.Inject;
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc compactDisc;
@Inject
public CDPlayer(CompactDisc compactDisc) {
this.compactDisc = compactDisc;
}
@Override
public void play() {
compactDisc.play();
}
}
Рекомендуется использовать аннотацию @Autowired в проектах Spring..
6. Проверьте автопроводку
Измените код класса CDPlayerTest, чтобы протестировать автоматическую сборку.
package chapter02;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.StandardOutputStreamLog;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
@Rule
public final StandardOutputStreamLog log = new StandardOutputStreamLog();
@Autowired
private MediaPlayer mediaPlayer;
@Autowired
private CompactDisc compactDisc;
@Test
public void cdShouldNotBeNull() {
assertNotNull(compactDisc);
compactDisc.play();
}
@Test
public void play() {
mediaPlayer.play();
assertEquals("Playing Sgt.Pepper's Lonely Hearts Club Band By The Beatles\r\n", log.getLog());
}
}
Поскольку в коде используется класс StandardOutputStreamLog, необходимо импортировать пакет jar: system-rules-1.16.0.jar Метод импорта пакета jar см.Начало работы с Spring (1): Создание проекта Spring.
Запустите тестовый метод play(), выходное содержимое будет таким же, как и ожидалось, что указывает на то, что поле mediaPlayer было собрано bean-компонентом класса реализации CDPlayer MediaPlayer, и тест проходит успешно, как показано ниже:
7. Исходный код и ссылка
Адрес источника:GitHub.com/Где находится Ухань/SPR…, добро пожаловать на скачивание.
Весна в действии (4-е издание) Крейга Уоллса