Архитектура Spring Boot для уменьшения зависимостей в частях приложения - PullRequest
1 голос
/ 27 сентября 2019

У нас есть приложение / коллекция приложений на основе весенней загрузки.Уже в первом предложении сложно описать его правильно, потому что с бизнес-точки зрения «вещь» - это одно приложение, а с технической точки зрения - как набор приложений весенней загрузки и сценариев обработки пакетных заданий одного бизнес-программного обеспечения.

Например, программное обеспечение состоит из приложения с загрузочной пружиной, предоставляющего rest-api, нескольких приложений с загрузочной пружиной, предоставляющих различные веб-сервисы, и нескольких пакетных заданий, выполняющих различные действия на основе приложений с загрузочной пружиной и других приложений.Теперь некоторые части кода используются только из одного из приложений весенней загрузки - так что это может быть легко размещено в этом конкретном приложении весенней загрузки.Но многие части кода используются из нескольких приложений с весенней загрузкой, но обычно меньше, чем половина приложений.Для этого бизнес-кода у нас есть центральный модуль, импортируемый всеми приложениями весенней загрузки.Добавление этого центрального модуля в приложение весенней загрузки увеличивает большое количество зависимостей (например, зависимость от системы CRM, зависимость от хранилища S3, зависимость для создания файлов Excel, зависимость от внешнего веб-сервиса, зависимость от кролика, ...).Чтобы избежать сотен зависимостей, мы определили многие из них как необязательные.Таким образом, каждое весеннее загрузочное приложение имеет только необходимые ему зависимости.

Проблема сейчас в центральном модуле с внедренными сервисами с бизнес-кодом.Эти услуги внедряются с помощью autowire.Например, приложение весенней загрузки, предоставляющее интерфейс веб-сервиса, не нуждается в сервисе для генерации файлов Excel и для этого не зависит от библиотек Excel и не нуждается в запуске сервиса генерации Excel.

Spring имеет возможность аннотировать сервисы с помощью @ConditionalOnClass и @ConditionalOnBean, но многие сервисы зависят не только от одного условия, но от двух или более.Итак, каков наилучший подход к структурированию сервисов, чтобы запускать их только при необходимости и / или при наличии необходимых зависимостей?

В настоящее время мы используем @ComponentScan с excludeFilters в каждом приложении весенней загрузки, но это подвержено ошибкам,Разделение центрального модуля на несколько модулей или микросервисов не вариант, потому что тогда модули содержат только от 1 до 5 классов.

Есть ли полезная практика для структурирования таких приложений?

Ответы [ 2 ]

0 голосов
/ 28 сентября 2019

Если ваш модуль объявляет общий модуль как зависимость, вы можете установить область действия этого модуля как «compile», а затем установить зависимости, которые должны быть исключены из общего модуля.

Я недавно столкнулсяСитуация, когда мне потребовался JPA в моем общем модуле для создания общих DAO для других модулей.Но я подумал, что было бы расточительно добавить такую ​​большую зависимость моего другого модуля, который не использовал JPA.

Это было решение:

<!-- ... -->
    <groupId>com.multimodule</groupId>
    <artifactId>server-app</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>

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

    <dependencies>
        <dependency>
            <groupId>com.multimodule</groupId>
            <artifactId>common</artifactId>
            <version>1.0.0-SNAPSHOT</version>
            <scope>compile</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-data-jpa</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.microsoft.sqlserver</groupId>
                    <artifactId>mssql-jdbc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    <!-- ... -->
    </dependencies>
<!-- ... -->

Таким образом, в дополнение к исключению связанных с JPA пакетов в общем модуле с использованием @ComponentScan, общая зависимость включается, когда серверМодуль -app компилируется, но не включает в себя jar-файлы JPA.

Если @ComponentScan не добавлено, модуль все равно будет скомпилирован, но, вероятно, будут исключения, как только бин будет подключен к общему, который попытается подключить бин к любому из исключенных jar-файлов.

Это верно в моем случае, поскольку мой общий модуль попытался бы автоматически настроить Jpa во время запуска, если бы он не был исключен, из-за @EnableAutoConfiguration в @SpringBootApplication.

0 голосов
/ 27 сентября 2019

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

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

Некоторое время назад я написал две статьи в блоге о том, как писать собственные стартовые загрузчики Spring.Это может быть хорошим началом для вас. Пост 1 и Пост 2 .

...