Перейти к содержанию

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

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

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

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

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

Автоконфигурации Spring Boot

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

Когда 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 и будут инициализированы все бины, связанные с mongo.

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

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

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

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

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

Посмотрим, как это работает.

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

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

    private String host;

    // другие поля со стандартными геттерами и сеттерами
}

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

spring.data.mongodb.host = localhost

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

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

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

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

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

Модуль автоконфигурации

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

Посмотрим на код для обоих классов:

@ConfigurationProperties(prefix = "baeldung.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.baeldung.greeter.autoconfigure.GreeterAutoConfiguration

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

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

Создание pom.xml

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

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

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

    <groupId>com.baeldung</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.baeldung</groupId>
            <artifactId>greeter-spring-boot-autoconfigure</artifactId>
            <version>${project.version}</version>
        </dependency>

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

    </dependencies>

</project>

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

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

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

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

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

baeldung.greeter.userName=Baeldung
baeldung.greeter.afternoonMessage=Woha\ Afternoon

Наконец, воспользуемся бином 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);
    }
}

Заключение

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

Исходный код всех модулей можно найти на GitHub.

Оригинал