1. Обзор
Именование bean-компонента Spring весьма полезно, когда у нас есть несколько реализаций одного и того же типа. Это связано с тем, что для Spring будет неоднозначно внедрить компонент, если наши компоненты не имеют уникальных имен.
Имея контроль над именованием bean-компонентов, мы можем указать Spring, какой bean-компонент мы хотим внедрить в целевой объект.
В этой статье мы обсудим стратегии именования компонентов Spring, а также рассмотрим, как мы можем дать несколько имен одному типу компонентов.
2. Стратегия именования компонентов по умолчанию
Spring предоставляет несколько аннотаций для создания bean-компонентов. Мы можем использовать эти аннотации на разных уровнях. Например, мы можем поместить некоторые аннотации в класс компонента, а другие — в метод, создающий компонент.
Во-первых, давайте посмотрим на стратегию именования Spring по умолчанию в действии. Как Spring называет наш компонент, когда мы просто указываем аннотацию без какого-либо значения?
2.1. Аннотации на уровне класса
Начнем со стратегии именования по умолчанию для аннотации, используемой на уровне класса. Чтобы назвать bean-компонент, Spring использует имя класса и преобразует первую букву в нижний регистр .
Давайте рассмотрим пример:
@Service
public class LoggingService {
}
Здесь Spring создает bean-компонент для класса LoggingService
и регистрирует его, используя имя « loggingService
».
Эта же стратегия именования по умолчанию применима ко всем аннотациям уровня класса, которые используются для создания bean-компонента Spring, например, @Component
, @Service
и @Controller
.
2.2. Аннотации уровня метода
Spring предоставляет аннотации, такие как @Bean
и @Qualifier
, которые можно использовать в методах создания bean-компонентов.
Давайте посмотрим на пример, чтобы понять стратегию именования по умолчанию для аннотации @Bean
:
@Configuration
public class AuditConfiguration {
@Bean
public AuditService audit() {
return new AuditService();
}
}
В этом классе конфигурации Spring регистрирует bean-компонент типа AuditService
под именем « audit
», потому что , когда мы используем аннотацию @Bean
для метода, Spring использует имя метода в качестве имени bean-компонента .
Мы также можем использовать аннотацию @Qualifier
для метода, и мы увидим пример ниже.
3. Пользовательское наименование бинов
Когда нам нужно создать несколько bean-компонентов одного типа в одном и том же контексте Spring, мы можем дать bean-компонентам собственные имена и ссылаться на них, используя эти имена.
Итак, давайте посмотрим, как мы можем дать собственное имя нашему компоненту Spring:
@Component("myBean")
public class MyCustomComponent {
}
На этот раз Spring создаст bean-компонент типа MyCustomComponent
с именем « myBean
».
Поскольку мы явно даем имя компоненту, Spring будет использовать это имя, которое затем можно использовать для обращения к компоненту или доступа к нему.
Подобно @Component("myBean")
, мы можем указать имя, используя другие аннотации, такие как @Service("myService")
, @Controller("myController")
и @Bean("myCustomBean")
, и тогда Spring зарегистрирует этот компонент с заданным именем.
4. Именование бина с помощью @Bean
и @Qualifier
4.1. @Бин
со значением
Как мы видели ранее, аннотация @Bean
применяется на уровне метода, и по умолчанию Spring использует имя метода в качестве имени компонента.
Это имя компонента по умолчанию может быть перезаписано — мы можем указать значение с помощью аннотации @Bean
:
@Configuration
public class MyConfiguration {
@Bean("beanComponent")
public MyCustomComponent myComponent() {
return new MyCustomComponent();
}
}
В этом случае, когда мы хотим получить компонент типа MyCustomComponent
, мы можем обратиться к этому компоненту, используя имя « beanComponent
».
Аннотация Spring @Bean
обычно объявляется в методах класса конфигурации. Он может ссылаться на другие методы @Bean
в том же классе, вызывая их напрямую.
4.2. @Квалификатор
со значением
Мы также можем использовать аннотацию @Qualifier
, чтобы назвать компонент.
Во-первых, давайте создадим интерфейс Animal
, который будет реализован несколькими классами:
public interface Animal {
String name();
}
Теперь давайте определим класс реализации Cat
и добавим к нему аннотацию @Qualifier
со значением « cat
»:
@Component
@Qualifier("cat")
public class Cat implements Animal {
@Override
public String name() {
return "Cat";
}
}
Давайте добавим еще одну реализацию Animal
и аннотируем ее @Qualifier
и значением « собака
»: ``
@Component
@Qualifier("dog")
public class Dog implements Animal {
@Override
public String name() {
return "Dog";
}
}
Теперь давайте напишем класс PetShow
, куда мы можем внедрить два разных экземпляра Animal
:
@Service
public class PetShow {
private final Animal dog;
private final Animal cat;
public PetShow (@Qualifier("dog")Animal dog, @Qualifier("cat")Animal cat) {
this.dog = dog;
this.cat = cat;
}
public Animal getDog() {
return dog;
}
public Animal getCat() {
return cat;
}
}
В классе Pet
Show
мы внедрили обе реализации типа Animal
, используя аннотацию @Qualifier
в параметрах конструктора с уточненными именами компонентов в атрибутах значений каждой аннотации. Всякий раз, когда мы используем это полное имя, Spring будет внедрять компонент с этим полным именем в целевой компонент.
5. Проверка имен компонентов
До сих пор мы видели разные примеры, демонстрирующие присвоение имен Spring bean-компонентам. Теперь вопрос в том, как мы можем проверить или проверить это?
Давайте посмотрим на модульный тест, чтобы проверить поведение:
@ExtendWith(SpringExtension.class)
public class SpringBeanNamingUnitTest {
private AnnotationConfigApplicationContext context;
@BeforeEach
void setUp() {
context = new AnnotationConfigApplicationContext();
context.scan("com.foreach.springbean.naming");
context.refresh();
}
@Test
void givenMultipleImplementationsOfAnimal_whenFieldIsInjectedWithQualifiedName_thenTheSpecificBeanShouldGetInjected() {
PetShow petShow = (PetShow) context.getBean("petShow");
assertThat(petShow.getCat().getClass()).isEqualTo(Cat.class);
assertThat(petShow.getDog().getClass()).isEqualTo(Dog.class);
}
В этом тесте JUnit мы инициализируем AnnotationConfigApplicationContext
в методе setUp
, который используется для получения компонента.
Затем мы просто проверяем класс наших bean-компонентов Spring, используя стандартные утверждения.
6. Заключение
В этой быстрой статье мы рассмотрели стандартные и пользовательские стратегии именования компонентов Spring.
Мы также узнали, как именование пользовательских компонентов Spring полезно в тех случаях, когда нам нужно управлять несколькими компонентами одного типа.
Как обычно, полный код для этой статьи доступен на GitHub .