Перейти к основному содержимому

Имена весенних бобов

· 5 мин. чтения

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 .