JavaRush /Курси /Spring Boot /Як читати build.gradle.kts...

Як читати build.gradle.kts

Spring Boot
Рівень 3 , Лекція 2
Відкрита

1. Роль build.gradle.kts у проєкті

Коли ви тільки починаєте, легко думати так: «Я пишу Java-код, отже, головний файл — це *.java, а все інше… ну, якась обгортка». На практиці ж build.gradle.kts — це домовленість проєкту зі світом: яку Java використовувати, які бібліотеки підключати, які команди запуску існують і чому в колеги все збирається, а у вас — ні.

Wrapper, toolchain і Boot plugin уже показали одну річ: важливі правила проєкту живуть не десь у повітрі, а прямо в build.gradle.kts. Тут вони складаються в єдині правила збірки проєкту, тож зараз важливо навчитися читати цей файл спокійно, блок за блоком.

Найнеприємніше в build.gradle.kts те, що він зазвичай привертає увагу тільки в момент болю: «чому не запускається», «чому тести не бачать JUnit», «чому не підтягуються залежності». Але добра новина в тому, що для рівня Junior не потрібно ставати Gradle-гуру. Достатньо вміти читати файл по блоках і розуміти, на яке запитання відповідає кожен із них.

Корисна установка на сьогодні: build.gradle.kts — це не «інша мова програмування», а конфігурація проєкту, записана в DSL, що виглядає як код.

2. Читання build.gradle.kts: чотири запитання

Якщо відкрити build.gradle.kts і спробувати «зрозуміти все одразу», мозок чесно скаже: «мені б краще в контролери…» (хоча ми поки туди не йдемо). Тому правильний спосіб — читати файл як документ із розділами. У кожного розділу є свій сенс і свій тип запитань, на які він відповідає.

Сприймайте читання build.gradle.kts як мініквест: ви йдете зверху вниз і щоразу ставите собі одне з чотирьох запитань.

Що бачу в build.gradle.kts На яке запитання це відповідає Як це відчувається в житті проєкту
plugins { ... }
«Які можливості увімкнені в збірці?» З’являються задачі на кшталт bootRun, вмикається створення boot-jar, підключається компіляція Java
repositories { ... }
«Звідки брати бібліотеки?» Gradle розуміє, де шукати залежності, а не дивиться на вас сумними очима
dependencies { ... }
«Що саме підключено до коду?» У проєкт приходять Spring Boot стартери та інші бібліотеки (компіляція, тести, обробка анотацій)
tasks ...
(налаштування задач)
«Які операції є і як вони налаштовані?» Тести запускаються на потрібній платформі, збірка поводиться передбачувано

Щоб закріпити картину, ось невелика «блок-схема» того, що реально відбувається, коли ви запускаєте Gradle-команду:

flowchart TD
    A["Ви: ./gradlew bootRun"] --> B["Gradle читає build.gradle.kts"]
    B --> C["Застосовує плагіни"]
    C --> D["Знає репозиторії"]
    D --> E["Розвʼязує залежності"]
    E --> F["Запускає завдання bootRun"]
    F --> G["Застосунок стартує"]

Це не магія. Це просто послідовність кроків. І зараз ми розберемо кожен блок так, щоб ви могли дивитися на нього спокійно — ну, або принаймні без бажання закрити ноутбук і піти в ліс.

Коли ця послідовність уже є в голові, build.gradle.kts перестає висіти в повітрі: за ним уже можна співвіднести збірку з деревом проєкту та стартерами.

3. plugins: суперсили збірки

Блок plugins зазвичай стоїть на початку файлу, і це логічно: спочатку ми кажемо Gradle, яким проєктом узагалі є, а вже потім — які бібліотеки нам потрібні. Плагін — це не «бібліотека для коду». Плагін — це розширення можливостей збірки: він додає задачі, змінює поведінку компіляції, пакування, запуску і може підтягнути додаткову логіку.

Наприклад, плагін java робить проєкт Java-проєктом: з’являється компіляція src/main/java, тести в src/test/java, стандартні задачі на кшталт compileJava і test. Плагін org.springframework.boot робить проєкт Boot-проєктом: додає задачі на кшталт bootRun, уміє збирати виконуваний jar у форматі boot і дає розумні значення за замовчуванням саме під Boot.

Маленький фрагмент типового блоку plugins для нашого catalog-service виглядає так:

plugins {
    // Базові задачі й угоди для Java-проєкту (compileJava, test тощо)
    java

    // Spring Boot приносить задачі bootRun/bootJar і налаштування збірки Boot
    id("org.springframework.boot") version "4.0.3"
}

Зверніть увагу на дві деталі. По-перше, id("...") — це ідентифікатор плагіна, а не Java package і не Maven coordinate. По-друге, у Boot plugin стоїть версія — це нормально, бо це основний плагін проєкту, і його версію важливо фіксувати.

Іноді поруч ви побачите ще один плагін, пов’язаний із керуванням версіями залежностей (наприклад, io.spring.dependency-management). Важливо не йти тут у глибоку теорію — просто зафіксуйте: такі плагіни належать до збірки, а не до коду, який виконуватиметься в застосунку. Їхнє завдання — зробити так, щоб вам не доводилося прописувати версії бібліотек вручну в кожному implementation.

Головна практична думка про plugins: якщо ви шукаєте, «чому зʼявилася задача bootRun» або «чому проєкт раптом став Boot-сервісом», найчастіше відповідь лежить саме тут.

4. repositories: джерела бібліотек

Слово «repository» у Java-світі трапляється занадто часто, і тому воно підступне. У Spring @Repository — це роль класу в застосунку (зазвичай шар доступу до даних). У Gradle repositories — це взагалі не про ваш код. Це про те, звідки завантажувати бібліотеки, які ви перелічили в dependencies.

Найчастіше в навчальних і звичайних проєктах ви побачите одне джерело — Maven Central. Це нормально і достатньо.

repositories {
    // Maven Central — основний публічний репозиторій, де лежить більшість бібліотек
    mavenCentral()
}

Уявіть, що dependencies — це ваш список покупок, а repositories — список магазинів, куди дозволено зайти. Якщо магазин не вказано, то навіть ідеальний список покупок не допоможе: Gradle просто не знає, де шукати ці «товари».

Є поширена спокуса додати якомога більше репозиторіїв — «раптом знадобиться». Для новачка це майже завжди погана ідея: зайві репозиторії ускладнюють діагностику, можуть уповільнювати збірку і іноді призводять до дивних ситуацій, коли одна й та сама бібліотека знаходиться в двох місцях, а ви раптом залежите від того, яка знайшлася першою.

На рівні цієї лекції тримаємо просте правило: якщо у вас mavenCentral(), ви вже молодець, нічого зайвого не треба.

5. dependencies: режими залежностей

Блок dependencies — найпомітніший і той, який редагують найчастіше. І саме тут новачок найчастіше робить дві помилки: або намагається підключити все підряд, або, навпаки, боїться додавати щось і тримається за мінімальний набір як за рятівне коло.

Важливий момент: у Gradle залежності підключаються не просто як список, а із зазначенням конфігурації. Конфігурація відповідає на запитання: «у якому режимі ця бібліотека потрібна?» Наприклад, чи потрібна вона для компіляції основного коду, лише для тестів, лише під час запуску або як обробник анотацій.

Мініприклад:

dependencies {
    // Потрібно основному коду застосунку (і буде в runtime classpath)
    implementation("org.springframework.boot:spring-boot-starter-webmvc")

    // Потрібно лише для тестів (у основний runtime не потрапить)
    testImplementation("org.springframework.boot:spring-boot-starter-test")
}

Тут implementation означає: «потрібно для основного коду застосунку». А testImplementation означає: «потрібно лише для тестів».

Щоб усе склалося в цілісну картину, ось невелика таблиця найчастіших конфігурацій — без спроби охопити весь всесвіт Gradle:

Конфігурація Де використовується Простий переклад людською мовою
implementation
основний код + runtime «Потрібно застосунку, коли він працює»
testImplementation
тести «Потрібно, щоб тести компілювалися і запускалися»
runtimeOnly
лише runtime «У компіляції не потрібно, але під час запуску має бути в classpath»
compileOnly
лише компіляція «Потрібно, щоб компілювалося, але в runtime не кладемо»
annotationProcessor
компіляція (обробка анотацій) «Потрібно компілятору, щоб генерувати щось на етапі збірки»

Наразі особливо важливі перші дві (implementation, testImplementation). Решту ми просто «впізнаємо в обличчя», щоб не лякатися, коли вони зʼявляться в проєкті.

Окрема важлива деталь у Boot-проєктах: ви часто побачите залежності без указання версії, наприклад:

implementation("org.springframework.boot:spring-boot-starter-webmvc")

І це не тому, що про це забули. Це нормальна Boot-ідея: версіями керує платформа (плагін або налаштування), щоб ви не перетворювали build.gradle.kts на таблицю із сотнею цифр. Сьогодні вам достатньо розуміти факт: «версії не завжди пишуться вручну — і це нормально».

6. tasks: задачі та налаштування

У якийсь момент ви прогортаєте build.gradle.kts до кінця і бачите блоки про tasks. У новачка зазвичай два режими: або «не чіпати», або «видалити, бо незрозуміло». Обидва режими, чесно кажучи, не дуже. Нормальний варіант — третій: «зрозуміти, що це таке, і не боятися читати».

Task (задача) Gradle — це іменована операція збірки. Компіляція, запуск тестів, пакування, запуск застосунку — все це задачі. Плагіни додають задачі, а tasks { ... } або tasks.named("...") { ... } дає змогу ці задачі налаштовувати.

У типових проєктах із JUnit таке налаштування виглядає так:

tasks.test {
    // Запускати тести через JUnit Platform
    useJUnitPlatform()
}

Це читається так: «налаштуй задачу test так, щоб вона запускала тести через JUnit Platform». Тут важливо, що ми не створюємо тести, не пишемо Java-код і не підключаємо бібліотеку. Ми налаштовуємо поведінку команди, яка виконуватиметься, коли ви зробите ./gradlew test.

Ще одна маленька, але важлива думка: задачі живуть не лише у файлі. Навіть якщо в build.gradle.kts взагалі немає блоку tasks, задачі все одно є — їх приносять плагіни. tasks — це просто місце, де ви їх підкручуєте, коли потрібно.

7. Типові помилки під час читання build.gradle.kts

Помилка №1: плутати repositories у Gradle і @Repository у Spring.
Звучить смішно, але трапляється постійно. У результаті людина починає «шукати репозиторій у коді», хоча це просто список джерел, звідки Gradle завантажує бібліотеки. Якщо ви бачите mavenCentral() — це не про шар даних застосунку і не про патерн Repository. Це про «магазин», звідки беруться jar-файли.

Помилка №2: вважати plugins і dependencies одним і тим самим.
Інтуїтивно хочеться думати: «і там, і там щось підключаємо». Але це різні світи. plugins розширюють збірку і додають задачі. dependencies додають бібліотеки в classpath вашого застосунку або тестів. Проста перевірка така: якщо ви очікуєте нову команду (bootRun, bootJar) — це плагін. Якщо ви очікуєте нові класи в Java-коді — це залежність.

Помилка №3: намагатися зрозуміти файл поверхово, а не глибше.
Новачок відкриває build.gradle.kts, бачить незнайомі слова, починає гуглити кожне і губиться в матеріалах рівня «внутрішня кухня Gradle». Робочий підхід навпаки: зрозуміти 4 блоки та їхній сенс, а деталі нарощувати поступово. Наразі достатньо, якщо ви впевнено впізнаєте plugins, repositories, dependencies, tasks.

Помилка №4: редагувати файл, не розуміючи, у якому блоці ви перебуваєте.
Це часта причина «чому воно взагалі не парситься». У Gradle DSL фігурні дужки — не декоративні. Якщо ви випадково додали залежність усередину repositories, отримаєте не «неправильну залежність», а синтаксичну помилку збірки. Тому перед зміною завжди корисно очима знайти: де блок відкривається і де закривається.

Помилка №5: сприймати tasks.test { ... } як «якусь магію Spring Boot».
Насправді це чистий Gradle: ми беремо задачу тестів і налаштовуємо її. Spring Boot тут поруч лише тому, що проєкт орієнтований на Boot, але сама конструкція — про Gradle. Якщо ви навчитеся читати tasks..., у вас різко впаде рівень тривожності при вигляді таких рядків.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ