1. Обзор
Spring 5 поставляется с поддержкой регистрации функциональных компонентов в контексте приложения.
Проще говоря, это можно сделать с помощью перегруженных версий нового метода registerBean()
, определенного в классе GenericApplicationContext
.
Давайте посмотрим на несколько примеров этой функциональности в действии.
2. Зависимости Maven
Самый быстрый способ настроить проект Spring 5
— использовать Spring Boot
, добавив зависимость spring-boot-starter-parent в
файл pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.1</version>
</parent>
Нам также нужны spring-boot-starter-web
и spring-boot-starter-test
для нашего примера, чтобы использовать контекст веб-приложения в тесте JUnit :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Конечно, Spring Boot
не нужен, чтобы использовать новый функциональный способ регистрации бина. Мы также могли бы просто добавить зависимость spring-core
напрямую:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.3</version>
</dependency>
3. Регистрация функционального компонента
API registerBean()
может принимать два типа функциональных интерфейсов в качестве параметров :
- аргумент
Поставщика
, используемый для создания объекта - BeanDefinitionCustomizer
vararg,
который можно использовать для предоставления одного или нескольких лямбда-выражений для настройкиBeanDefinition
; этот интерфейс имеет единственный методcustom()
Во-первых, давайте создадим очень простое определение класса, которое мы будем использовать для создания bean-компонентов:
public class MyService {
public int getRandomNumber() {
return new Random().nextInt(10);
}
}
Давайте также добавим класс @SpringBootApplication
, который мы можем использовать для запуска теста JUnit :
@SpringBootApplication
public class Spring5Application {
public static void main(String[] args) {
SpringApplication.run(Spring5Application.class, args);
}
}
Затем мы можем настроить наш тестовый класс, используя аннотацию @SpringBootTest
для создания экземпляра GenericWebApplicationContext
:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Spring5Application.class)
public class BeanRegistrationIntegrationTest {
@Autowired
private GenericWebApplicationContext context;
//...
}
В нашем примере мы используем тип GenericWebApplicationContext
, но любой тип контекста приложения может использоваться таким же образом для регистрации компонента.
Давайте посмотрим, как мы можем зарегистрировать bean-компонент, используя лямбда-выражение для создания экземпляра :
context.registerBean(MyService.class, () -> new MyService());
Давайте проверим, что теперь мы можем получить компонент и использовать его:
MyService myService = (MyService) context.getBean("com.foreach.functional.MyService");
assertTrue(myService.getRandomNumber() < 10);
В этом примере мы видим, что если имя компонента не определено явно, оно будет определено из имени класса в нижнем регистре. Тот же метод выше также можно использовать с явным именем компонента:
context.registerBean("mySecondService", MyService.class, () -> new MyService());
Далее давайте посмотрим, как мы можем зарегистрировать bean-компонент, добавив лямбда-выражение для его настройки :
context.registerBean("myCallbackService", MyService.class,
() -> new MyService(), bd -> bd.setAutowireCandidate(false));
Этот аргумент является обратным вызовом, который мы можем использовать для установки свойств бина, таких как флаг кандидата автоподключения
или первичный
флаг.
4. Вывод
В этом кратком руководстве мы увидели, как мы можем использовать функциональный способ регистрации компонента.
Исходный код примера можно найти на GitHub .