Начало работы с Spring (2): автоматическая сборка компонентов

Spring

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-е издание) Крейга Уоллса