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

Создание пользовательского стартера с Spring Boot

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

Задача: Медиана двух отсортированных массивов

Даны два отсортированных массива размерами n и m. Найдите медиану слияния этих двух массивов.
Временная сложность решения должна быть O(log(m + n)) ...

ANDROMEDA

1. Обзор

Основные разработчики Spring Boot предоставляют стартеры для большинства популярных проектов с открытым исходным кодом, но мы не ограничиваемся ими.

Мы также можем написать свои собственные стартеры . Если у нас есть внутренняя библиотека для использования в нашей организации, было бы неплохо также написать для нее стартер, если он будет использоваться в контексте Spring Boot.

Эти стартеры позволяют разработчикам избежать длительной настройки и быстро приступить к разработке. Однако из-за того, что в фоновом режиме происходит множество вещей, иногда становится трудно понять, как аннотация или просто включение зависимости в pom.xml позволяет использовать так много функций.

В этой статье мы демистифицируем магию Spring Boot, чтобы увидеть, что происходит за кулисами. Затем мы воспользуемся этими концепциями, чтобы создать стартер для нашей собственной пользовательской библиотеки.

2. Демистификация автоконфигурации Spring Boot

2.1. Классы автоматической настройки

Когда Spring Boot запускается, он ищет файл с именем spring.factories в пути к классам. Этот файл находится в каталоге META-INF . Давайте посмотрим на фрагмент этого файла из проекта spring-boot-autoconfigure :

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration

Этот файл сопоставляет имя с различными классами конфигурации, которые Spring Boot попытается запустить. Итак, согласно этому фрагменту, Spring Boot попытается запустить все классы конфигурации для RabbitMQ, Cassandra, MongoDB и Hibernate.

Будут ли эти классы работать на самом деле, будет зависеть от наличия зависимых классов в пути к классам. Например, если классы для MongoDB будут найдены в пути к классам, запустится MongoAutoConfiguration и будут инициализированы все bean-компоненты, связанные с mongo.

Эта условная инициализация включается аннотацией @ConditionalOnClass . Давайте посмотрим на фрагмент кода из класса MongoAutoConfiguration , чтобы увидеть его использование:

@Configuration
@ConditionalOnClass(MongoClient.class)
@EnableConfigurationProperties(MongoProperties.class)
@ConditionalOnMissingBean(type = "org.springframework.data.mongodb.MongoDbFactory")
public class MongoAutoConfiguration {
// configuration code
}

Теперь, как — если MongoClient доступен в пути к классам — этот класс конфигурации будет запускаться, заполняя фабрику bean-компонентов Spring с MongoClient , инициализированным с настройками конфигурации по умолчанию.

2.2. Пользовательские свойства из файла application.properties

Spring Boot инициализирует bean-компоненты, используя некоторые предварительно настроенные значения по умолчанию. Чтобы переопределить эти значения по умолчанию, мы обычно объявляем их в файле application.properties с определенным именем. Эти свойства автоматически подхватываются контейнером Spring Boot.

Давайте посмотрим, как это работает.

Во фрагменте кода для MongoAutoConfiguration аннотация @EnableConfigurationProperties объявлена с классом MongoProperties , который действует как контейнер для пользовательских свойств:

@ConfigurationProperties(prefix = "spring.data.mongodb")
public class MongoProperties {

private String host;

// other fields with standard getters and setters
}

Префикс плюс имя поля составляют имена свойств в файле application.properties . Итак, чтобы установить хост для MongoDB, нам нужно всего лишь написать в файле свойств следующее:

spring.data.mongodb.host = localhost

Точно так же значения для других полей в классе могут быть установлены с помощью файла свойств.

3. Создание пользовательского стартера

Основываясь на концепциях, изложенных в разделе 2, для создания пользовательского стартера нам необходимо написать следующие компоненты:

  1. Класс автоматической настройки для нашей библиотеки вместе с классом свойств для пользовательской конфигурации.
  2. Стартовый pom для ввода зависимостей библиотеки и проекта автоконфигурации.

Для демонстрации мы создали простую библиотеку приветствий , которая принимает приветственное сообщение для разного времени суток в качестве параметров конфигурации и выводит приветственное сообщение. Мы также создадим пример приложения Spring Boot, чтобы продемонстрировать использование наших модулей автонастройки и запуска.

3.1. Модуль автонастройки

Мы назовем наш модуль автоматической настройки Greeter-spring-boot-autoconfigure . Этот модуль будет иметь два основных класса : GreeterProperties , который позволит устанавливать пользовательские свойства через файл application.properties , и GreeterAutoConfiguartion , который создаст bean-компоненты для библиотеки приветствия .

Давайте посмотрим на код для обоих классов:

@ConfigurationProperties(prefix = "foreach.greeter")
public class GreeterProperties {

private String userName;
private String morningMessage;
private String afternoonMessage;
private String eveningMessage;
private String nightMessage;

// standard getters and setters

}
@Configuration
@ConditionalOnClass(Greeter.class)
@EnableConfigurationProperties(GreeterProperties.class)
public class GreeterAutoConfiguration {

@Autowired
private GreeterProperties greeterProperties;

@Bean
@ConditionalOnMissingBean
public GreetingConfig greeterConfig() {

String userName = greeterProperties.getUserName() == null
? System.getProperty("user.name")
: greeterProperties.getUserName();

// ..

GreetingConfig greetingConfig = new GreetingConfig();
greetingConfig.put(USER_NAME, userName);
// ...
return greetingConfig;
}

@Bean
@ConditionalOnMissingBean
public Greeter greeter(GreetingConfig greetingConfig) {
return new Greeter(greetingConfig);
}
}

Нам также нужно добавить файл spring.factories в каталог src/main/resources/META-INF со следующим содержимым:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.foreach.greeter.autoconfigure.GreeterAutoConfiguration

При запуске приложения будет запущен класс GreeterAutoConfiguration , если класс Greeter присутствует в пути к классам. В случае успешного запуска он заполнит контекст приложения Spring компонентами GreeterConfig и Greeter , прочитав свойства через класс GreeterProperties .

Аннотация @ConditionalOnMissingBean гарантирует , что эти bean-компоненты будут созданы только в том случае, если они еще не существуют. Это позволяет разработчикам полностью переопределить автоматически настроенные bean-компоненты, определив свои собственные в одном из классов @Configuration .

3.2. Создание pom.xml

Теперь давайте создадим начальный pom , который будет включать зависимости для модуля автоматической настройки и библиотеки приветствия.

Согласно соглашению об именах, все стартеры, которыми не управляет основная команда Spring Boot, должны начинаться с имени библиотеки, за которым следует суффикс -spring-boot-starter . Итак, мы назовем наш стартер как Greeter-spring-boot-starter:

<project ...>
<modelVersion>4.0.0</modelVersion>

<groupId>com.foreach</groupId>
<artifactId>greeter-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<greeter.version>0.0.1-SNAPSHOT</greeter.version>
<spring-boot.version>2.2.6.RELEASE</spring-boot.version>
</properties>

<dependencies>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot.version}</version>
</dependency>

<dependency>
<groupId>com.foreach</groupId>
<artifactId>greeter-spring-boot-autoconfigure</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.foreach</groupId>
<artifactId>greeter</artifactId>
<version>${greeter.version}</version>
</dependency>

</dependencies>

</project>

3.3. Использование стартера

Давайте создадим приложениеgreeter-spring-boot-sample-app, которое будет использовать файл starter. В pom.xml нам нужно добавить его как зависимость:

<dependency>
<groupId>com.foreach</groupId>
<artifactId>greeter-spring-boot-starter</artifactId>
<version>${greeter-starter.version}</version>
</dependency>

Spring Boot автоматически все настроит, и у нас будет готовый bean-компонент Greeter для внедрения и использования.

Давайте также изменим некоторые значения GreeterProperties по умолчанию, определив их в файле application.properties с префиксом foreach.greeter :

foreach.greeter.userName=ForEach
foreach.greeter.afternoonMessage=Woha\ Afternoon

Наконец, давайте воспользуемся bean- компонентом Greeter в нашем приложении:

@SpringBootApplication
public class GreeterSampleApplication implements CommandLineRunner {

@Autowired
private Greeter greeter;

public static void main(String[] args) {
SpringApplication.run(GreeterSampleApplication.class, args);
}

@Override
public void run(String... args) throws Exception {
String message = greeter.greet();
System.out.println(message);
}
}

4. Вывод

В этом кратком руководстве мы сосредоточились на развертывании пользовательского стартера Spring Boot и на том, как эти стартеры вместе с механизмом автонастройки работают в фоновом режиме, чтобы исключить большую часть ручной настройки.

Полный исходный код всех модулей, которые мы создали в этой статье, можно найти на GitHub .