Як Spring Boot реалізує залежності кастомних стартерів

pic

Джерело зображення

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

Огляд стартерів Spring Boot

Стартери Spring Boot — це спеціалізовані модулі залежностей, призначені для того, щоб об'єднати колекцію бібліотек, конфігурацій та інших супутніх ресурсів в один узгоджений артефакт. Ці стартери є основою підходу Spring Boot до управління залежностями та модульного дизайну додатків, що дозволяє розробникам швидко інтегрувати та конфігурувати складні функції додатків без необхідності вручну вказувати чи налаштовувати кожну залежність.

Анатомія стартера Spring Boot

В основі стартерів лежать просто залежності Maven або Gradle з визначеною структурою та специфічними умовами. Вони призначені для того, щоб полегшити додавання кількох пов'язаних бібліотек шляхом упаковки їх в одну залежність.

Наприклад, стартер spring-boot-starter-web включає:

  1. Spring MVC: для обробки веб-запитів.
  2. Jackson: для обробки JSON.
  3. Tomcat (або Jetty): як сервер за замовчуванням.

Це означає, що включення spring-boot-starter-web у вашому проєкті автоматично додасть всі ці залежності разом з їх транзитивними залежностями, базуючись на конфігурації pom.xml або build.gradle стартеру.

Механізм вирішення залежностей

Коли стартер Spring Boot додається до проєкту, інструмент збірки (наприклад, Maven або Gradle) вирішує його залежності рекурсивно. Наприклад, якщо стартер вказує бібліотеку spring-web як залежність, Maven завантажить цю бібліотеку та всі додаткові залежності, оголошені в її власному pom.xml. Цей ієрархічний процес вирішення залежностей спрощує управління залежностями, але вимагає точного налаштування в модулі стартера, щоб уникнути конфліктів версій або зайвого навантаження.

Добре спроектований стартер залежить від:

  1. Виключень: для усунення конфліктуючих або небажаних транзитивних залежностей.
  2. Обмежень залежностей: для контролю версій основних бібліотек і забезпечення сумісності з усією екосистемою Spring.

Як стартери Spring Boot інтегруються з автоконфігурацією

Хоча стартери самі по собі упаковують бібліотеки, вони також слугують як каталізатори для автоконфігурації в Spring Boot. Коли стартер додається до проєкту, він часто працює в тандемі з механізмом автоконфігурації Spring Boot, який динамічно активує біні (beans) та конфігурації на основі наявності конкретних класів, властивостей або інших умов.

Наприклад:

  • Додавши spring-boot-starter-data-jpa до вашого проєкту, ви отримаєте Hibernate як залежність.
  • Механізм автоконфігурації виявляє наявність Hibernate і автоматично конфігурує DataSource, EntityManagerFactory та менеджер транзакцій.

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

Переваги агрегації залежностей у стартерів

Агрегація залежностей у стартерів — це не лише зручність. Це відображає архітектурний принцип визначення узгоджених модулів, які інкапсулюють як функціональність, так і конфігурацію.
Цей підхід зменшує когнітивне навантаження для розробників, абстрагуючи вибір бібліотек, керування версіями та тестування сумісності.

Наприклад:

  • Під час роботи з Spring Security додавання spring-boot-starter-security вводить базову конфігурацію, яка включає безпечні налаштування за замовчуванням, дозволяючи розробникам зосередитись на налаштуванні поведінки додатка, а не на його початковій конфігурації.

Створення кастомного модуля-стартера

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

Ініціалізація модуля

Перший крок при створенні кастомного стартеру — це створення нового Maven або Gradle модуля. Цей модуль служить контейнером для залежностей та конфігурацій, які ви хочете упакувати. Модуль-стартер має мати тип пакування jar і явно вказувати свої залежності у файлі pom.xml або build.gradle.

Maven pom.xml:


 com.example  
 custom-starter  
 1.0.0  
 jar  



 org.springframework.boot  
 spring-boot-autoconfigure  




У цій конфігурації включено spring-boot-autoconfigure, щоб надати доступ до фреймворку автоконфігурації Spring Boot, який є необхідним для більшості кастомних стартерів.

Структурування модуля-стартера

Кастомний стартер потребує специфічних структурних елементів для безперешкодної інтеграції з Spring Boot. Типова структура каталогів та файлів виглядає наступним чином:

src/main/java/com/example/config/  
 └── MyAutoConfiguration.java  
src/main/resources/META-INF/  
 └── spring.factories
  1. Клас автоконфігурації: цей клас визначає біні (beans) і конфігурації, які надаються стартером.
  2. Файл spring.factories: цей файл необхідний для реєстрації класу автоконфігурації в механізмі автоконфігурації Spring Boot.

Додавання залежностей і виключень

Файл pom.xml має визначати залежності, які стартер надасть споживаючим додаткам. Важливо ретельно вибирати ці залежності, щоб уникнути непотрібних транзитивних залежностей.

Приклад:


 com.example  
 my-library  
 1.0.0  
 compile  


 org.springframework  
 spring-context  

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

Приклад виключення транзитивних залежностей:


 com.example  
 my-library  
 1.0.0  


 org.slf4j  
 slf4j-api  



Реєстрація автоконфігурації

Файл spring.factories є критичним компонентом, що з’єднує модуль-стартер із системою автоконфігурації Spring Boot.
Цей файл повинен бути розміщений в директорії src/main/resources/META-INF/ і містити повні кваліфіковані імена класів автоконфігурації.

Приклад:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\  
com.example.config.MyAutoConfiguration

Цей файл вказує Spring Boot, що необхідно включити MyAutoConfiguration в процес автоконфігурації, коли модуль-стартер знаходиться в classpath.

Реалізація класу автоконфігурації

Клас автоконфігурації — це місце, де визначається повторно використовувана функціональність. Він анотований як @Configuration, щоб позначити його як клас конфігурації Spring, і часто використовує умовні анотації для контролю його активації.

Приклад:

package com.example.config;  

import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  

@Configuration  
public class MyAutoConfiguration {  

 @Bean  
 public MyService myService() {  
 return new MyService();  
 }  
}

У наведеному прикладі визначено бін MyService, який автоматично створюється та додається до контексту додатка, коли використовується стартер.

Тестування стартера

Тестування є важливим етапом для перевірки, чи правильно інтегрується стартер з додатками Spring Boot. Це можна зробити, створивши зразковий додаток, що включає стартер як залежність.

  • Додайте кастомний стартер до pom.xml зразкового додатка:

 com.example  
 custom-starter  
 1.0.0  

  • Перевірте, чи біні та конфігурації, надані стартером, завантажуються як очікується:
@SpringBootApplication  
public class TestApplication {  
 public static void main(String[] args) {  
 ApplicationContext context = SpringApplication.run(TestApplication.class, args);  
 MyService myService = context.getBean(MyService.class);  
 System.out.println(myService.getMessage());  
 }  
}

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

Автоконфігурація та інтеграція залежностей

Автоконфігурація — це основна функція Spring Boot, розроблена для динамічного налаштування контексту додатка на основі залежностей, доступних у classpath, та різних умов виконання. Цей механізм є основою для інтеграції кастомних модулів-стартерів, дозволяючи їм надавати попередньо налаштовану функціональність без необхідності вручну налаштовувати все розробнику.

Механізм автоконфігурації

Автоконфігурація працює через умовні анотації, класи конфігурації та механізм spring.factories.
Коли додаток запускається, Spring Boot сканує класи автоконфігурації, вказані у файлі META-INF/spring.factories, оцінює їх умови і застосовує їх до контексту додатка, якщо умови виконуються.

Завантажувач Spring Factories:

  • Spring Boot використовує клас SpringFactoriesLoader для завантаження всіх повних імен класів, вказаних під org.springframework.boot.autoconfigure.EnableAutoConfiguration у файлі spring.factories.
  • Ці класи завантажуються в контекст додатка у вказаному порядку, що дозволяє здійснювати модульну та гнучку конфігурацію.

Приклад запису в spring.factories:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\  
com.example.config.MyAutoConfiguration,\  
com.example.config.OtherAutoConfiguration

Умовні анотації:

  • Умовні анотації, як-от @ConditionalOnClass, @ConditionalOnMissingBean та @ConditionalOnProperty, визначають, чи має бути включений певний клас автоконфігурації або бін.
  • Ці умови дозволяють вибірково активувати конфігурацію в залежності від наявності певних класів, бінів або властивостей.

Приклад:

@Configuration  
@ConditionalOnClass(name = "com.example.library.MyLibrary")  
public class MyLibraryAutoConfiguration {  

 @Bean  
 public MyLibraryService myLibraryService() {  
 return new MyLibraryService();  
 }  
}

У цьому прикладі бін MyLibraryService реєструється тільки тоді, коли клас com.example.library.MyLibrary присутній у classpath.

Інтеграція залежностей у стартери

Кастомні стартери часто надають не тільки конфігурації, але й бібліотеки, від яких залежить система автоконфігурації. Процес інтеграції включає:

Агрегація залежностей:

  • Стартери включають всі необхідні бібліотеки як частину їх декларації залежностей, гарантуючи, що споживаючий додаток має все необхідне для роботи з автоконфігурацією стартера.

Приклад залежностей для стартера:


 org.springframework  
 spring-context  


 com.example  
 my-library  

Розв'язання транзитивних залежностей:

  • Коли стартер додається до проєкту, інструмент для побудови рекурсивно розв'язує транзитивні залежності. Якщо my-library залежить від додаткових бібліотек, вони автоматично додаються до споживаючого додатка.

Виключення непотрібних залежностей:

  • Для уникнення зайвих залежностей можна оголосити виключення у конфігурації залежностей стартера.

Приклад виключення залежностей:


 com.example  
 my-library  


 org.slf4j  
 slf4j-api  



Умовна конфігурація на основі властивостей

Поширений шаблон в автоконфігурації — це використання властивостей для контролю активації конкретних конфігурацій. Анотація @ConditionalOnProperty дозволяє розробникам прив'язувати конфігурації до конкретних властивостей, визначених у конфігураційних файлах додатка.

Приклад:

@Configuration  
@ConditionalOnProperty(name = "custom.feature.enabled", havingValue = "true")  
public class FeatureAutoConfiguration {  

 @Bean  
 public FeatureService featureService() {  
 return new FeatureService();  
 }  
}

У цьому випадку бін FeatureService реєструється тільки тоді, коли властивість custom.feature.enabled встановлена в значення true у файлі application.properties або application.yml.

Інтеграційне тестування автоконфігурації

Після реалізації автоконфігурації тестування її поведінки є критичним для перевірки правильної інтеграції з екосистемою Spring Boot.
Інтеграційні тести можуть підтвердити, що очікувані біни завантажені на основі заданих умов.

Тестування за допомогою @SpringBootTest:

@SpringBootTest(properties = "custom.feature.enabled=true")  
class FeatureAutoConfigurationTest {  

 @Autowired  
 private FeatureService featureService;  

 @Test  
 void featureServiceShouldBeAvailable() {  
 assertNotNull(featureService);  
 }  
}

Цей тест перевіряє, що бін FeatureService реєструється в контексті додатка, коли властивість custom.feature.enabled встановлена в значення true.

Висновок

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

  1. Офіційна документація Spring Boot
  2. Автоконфігурація Spring Boot
  3. Завантажувач Spring Factories

Дякую за прочитання! Якщо ця стаття була корисною, будь ласка, розгляньте можливість підкреслити, аплодувати, відповісти або зв'язатися зі мною через Twitter/X це буде дуже приємно і допоможе тримати контент, подібний до цього, безкоштовним!

pic

Іконка Spring Boot від Icons8

Перекладено з: How Spring Boot Implements Custom Starter Dependencies

Leave a Reply

Your email address will not be published. Required fields are marked *