Приходить! Написать spring-boot-starter вручную

задняя часть
Приходить! Написать spring-boot-starter вручную

предисловие

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

Итак, вы разработали некоторые основные функции в реальной разработке, которые необходимо использовать в вашем проекте Spring Boot?

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

Мы можем сделать нашу функцию в соответствующем Starter-модуле и добавить ее непосредственно как зависимость Maven, когда она будет использоваться в проекте, Таким образом, нам не только не нужно повторять разработку, но и когда функция обновлено, есть более хорошее управление версиями.

Создание весеннего загрузочного стартера

Далее соберём spring-boot-starter.Для удобства описания предполагается, что основная функция нашего Starter — это удобно отправлять и получать асинхронные события. Обратите внимание, что цель этой статьи в основном рассказать о том, как собрать Starter, поэтому детали реализации отправки и получения асинхронных событий описываться не будут.

Базовые концепты

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

Application Context

Если вы что-то знаете о Spring, вы должны знать Application Context, который является контейнером для управления Spring bean-компонентами, который содержит все объекты в нашем проекте, такие как Controller, Service, Repository, Component и т. д.

@Configuration

@ConfigurationЭто аннотация в Spring.Класс, помеченный этой аннотацией, эквивалентен XML-файлу конфигурации Spring.Его основная цель - предоставить некоторые объекты Bean для контекста приложения. вы можете понять это как@ConfigurationАннотированный класс представляет собой фабрику объектов Bean.

Auto-Configuration

В Spring Boot есть@EnableAutoConfigurationаннотация, там написаноspring.factoriesв файлеEnableAutoConfigurationКласс, указанный ниже, для инициализации всех добавленных ниже указанного класса@Beanметод и инициализировать этот bean-компонент. И может указать условия, в соответствии с конкретными условиями, чтобы решить, следует ли автоматически собирать объект Bean.


Создать проект

Затем мы начинаем сборку нашего Starter, мы даем ему имя с именемspring-boot-starter-eventmessage.

Предположим, нам нужно реализовать микросервисную среду, обеспечивающую асинхронную связь между различными сервисами. нашspring-boot-starter-eventmessageВ основном обеспечивают следующие функции:

  • Во-первых, нам нужно иметьEventPublisherобъект, который используется для отправки событий в центр сообщений;
  • тогда должен бытьEventListenerКласс для подписки на определенные события из центра сообщений;

Поскольку наш Starter должен использоваться в нескольких микросервисных приложениях, наш Starter должен иметь возможность использовать Maven для его создания, чтобы облегчить внедрение других приложений.

Сначала давайте создадим проект mavenspring-boot-starter-eventmessage.

pom.xmlФайлы следующие:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.heiz123</groupId>
    <artifactId>spring-boot-starter-eventmessage</artifactId>
    <version>1.0.0</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>2.4.2</version>
        </dependency>
    </dependencies>

</project>

Пусть стартер autowire

Затем нам нужно предоставить запись для нашей функции Starter, нам нужно предоставить@Configurationсвоего рода:

@Configuration
public class EventAutoConfiguration {

    @Bean
    public EventPublisher eventPublisher(List<EventListener> listeners) {
        return new EventPublisher(listeners);
    }

EventAutoConfigurationВключите все определения @Bean, необходимые для обеспечения функциональности Starter. Потому что нашему Стартеру нужно только предоставить функцию публикации событий, поэтому здесь главное перейти кApplicationContextдобавитьEventPublisherобъект.

нашEventPublisherнужно знать всеEventListener, поэтому он может доставлять им события, поэтому мы позволяем Spring внедритьApplicationContextвсе доступно вEventListenerСписок.

Далее идет важная часть, как сделать наш Starter автоматически настроенным?META-INF/создать каталогspring.factoriesдокумент.

В этом файле настраиваем нашуConfigurationсвоего рода:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.heiz123.event.EventAutoConfiguration

Spring Boot будет искать все пути к классамspring.Factoriesфайл и загрузите объявленную в нем конфигурацию.

имеютEventAutoConfigurationПосле урока у нас теперь есть точка входа, которая может автоматически связывать spring-boot-starter.

Сделать поддержку Starter опциональной

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

Мы можем использовать Spring BootConditionalАннотации делают нашуConfigurationстановится необязательным:

@Configuration
@ConditionalOnProperty(value = "eventstarter.enabled", havingValue = "true")
@ConditionalOnClass(name = "com.heiz123.RabbitConnector")
@Slf4j
public class EventAutoConfiguration {

    @Bean
    public EventPublisher eventPublisher(List<EventListener> listeners) {
        log.info("event-message 自动装配中...");
        return new EventPublisher(listeners);
    }
}

@ConditionalOnPropertyЭффект аннотаций заключается в том, что толькоeventstarter.enabledсвойство установлено наtrue, будетEventAutoConfigurationдобавить вApplicationContextсередина. Таким образом, в приложении, которое использует наш стартер, вы можете пройтиeventstarter.enabledсвойство, чтобы динамически контролировать, включен ли наш стартер.

@ConditionalOnClassЭффект аннотаций только вclasspathТамcom.heiz123.RabbitConnectorclass для активации автоконфигурации.

Сделать Starter настраиваемым

в нашемEventAutoConfiguration, вам нужно ввести всеEventListenerнашимEventPublisher, но можно использовать наше приложение Starter и не хотеть, чтобы всеEventListenerВся обработка, может быть, только часть внимания к событию, тогда мы должны поддерживать пользователя, чтобы его можно было легко настроить.

Например, в файле application.properties или файле application.yml вы можете настроить следующее:

eventstarter.listener.enabled-events:foo,bar

yml-файл:

eventstarter:
  listener:
    enabled-events:
      - foo
      - bar

Чтобы легко получить доступ к этим свойствам в коде Starter, мы можем предоставить@ConfigurationPropertiesсвоего рода:

@ConfigurationProperties(prefix = "eventstarter.listener")
class EventListenerProperties {

    /**
     * 会被传递给EventListener中的所有Event的类型。
     * 其他Event将会被忽略
     */
    private List<String> enabledEvents = Collections.emptyList();

    public List<String> getEnabledEvents() {
        return enabledEvents;
    }

    public void setEnabledEvents(List<String> enabledEvents) {
        this.enabledEvents = enabledEvents;
    }
}

Затем мы используем@EnableConfigurationPropertiesАннотируйте нашу конфигурацию точки входа, чтобы включитьEventListenerPropertiesсвоего рода:

@Configuration
@EnableConfigurationProperties(EventListenerProperties.class)
@Slf4j
public class EventAutoConfiguration {

    @Bean
    public EventPublisher eventPublisher(List<EventListener> listeners) {
        log.info("event-message 自动装配中...");
        return new EventPublisher(listeners);
    }
}

Наконец, мы можем вводить, где это необходимоEventListenerPropertiesобъекты, такие как абстрактныеEventListenerОтфильтруйте события, не представляющие интереса для класса:

public abstract class EventListener {

    private final EventListenerProperties properties;

    public EventListener(EventListenerProperties properties) {
        this.properties = properties;
    }

    public void receive(Event event) {
        // 如果事件是Eanbled并且订阅了。
        if (isEnabled(event) && isSubscribed(event)) {
            onEvent(event);
        }
    }

    private boolean isSubscribed(Event event) {
        return event.getType().equals(getSubscribedEventType());
    }

    private boolean isEnabled(Event event) {
        return properties.getEnabledEvents().contains(event.getType());
    }

    protected abstract String getSubscribedEventType();

    protected abstract void onEvent(Event event);
}

На данный момент наш Starter в основном может использоваться другими.

начать использовать

Практика — единственный критерий проверки истины. Давайте представим нашуspring-boot-starter-eventmessage.

Сначала создайте проект spring-boot, мы называем егоtest-starter.

Затем нам просто нужно добавить информацию о координатах зависимостей Starter в Maven.

        <dependency>
            <groupId>com.heiz123</groupId>
            <artifactId>spring-boot-starter-eventmessage</artifactId>
            <version>1.0.0</version>
        </dependency>

Затем запустите наш проект SpringBoot. Стартовый класс выглядит следующим образом:

@SpringBootApplication
public class Main {

    public static void main(String[] args) {
        try {
            SpringApplication.run(Main.class, args);
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
}

результат операции:

Укажите, что мы успешно интегрировалисьspring-boot-starter-eventmessage.

Суммировать

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

Предоставляет класс автоматической конфигурации Configuration, который можно отключать и включать, а также предоставляет настраиваемые параметры для некоторой переменной информации.

Выше приведено полное содержание этого выпуска. Если это было полезно для вас, пожалуйста, не забудьте поставить мне три лайка подряд!

Я Сяо Хей, программист, который «выслеживает» Интернет.

Текущая вода не соревнуется за первое, а говорить дорого