Введение в Gradle для Java
Что такое Gradle, чем он отличается от Maven и как настроить проект Java с помощью Gradle.
Gradle — это инструмент автоматизации сборки для JVM (и не только), который компилирует код, запускает тесты, управляет зависимостями и упаковывает результат — всё это управляется скриптом сборки, написанным на Groovy или Kotlin. Там, где Maven описывает проект фиксированным XML, Gradle описывает его кодом: скрипт сборки конфигурирует граф задач. Именно этот переход к программируемой модели в сочетании с инкрементальным кешем сборки, пропускающим уже выполненную работу, сделал Gradle основным инструментом для Android и многих крупных Java-проектов.
Gradle vs. Maven
Оба инструмента решают одну задачу — воспроизводимые сборки с управляемыми зависимостями — но делают разные компромиссы. Если вы уже знакомы с Maven, вот сравнительная таблица:
| Аспект | Maven | Gradle |
|---|---|---|
| Файл сборки | pom.xml (XML) | build.gradle (Groovy) или build.gradle.kts (Kotlin) |
| Модель | Фиксированные фазы жизненного цикла | Настраиваемый граф задач (DAG) |
| Расширяемость | Плагины, привязанные к фазам | Плагины и встроенные ad-hoc-задачи |
| Инкрементальная сборка | Ограничена | Полноценная: проверка актуальности + кеш сборки |
| Обёртка | необязательна | gradlew — стандарт, фиксирует версию Gradle |
| Многословность | Больше шаблонного кода | Лаконичнее, но больше «магии» для изучения |
Ни один из них не является однозначно лучшим. Жёсткость Maven делает сборки предсказуемыми; гибкость Gradle позволяет выражать сложные сборки. В этой части рассматривается Gradle; введение в Maven охватывает другую сторону.
Минимальный скрипт сборки Java
Проект Java на Gradle — это один файл build.gradle и стандартная структура исходников (src/main/java, src/test/java). Подключение встроенного плагина java обучает Gradle компилировать, тестировать и создавать jar:
plugins {
id 'java'
}
group = 'com.example'
version = '1.0.0'
repositories {
mavenCentral()
}
dependencies {
implementation 'com.google.guava:guava:33.0.0-jre'
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
}Kotlin DSL (build.gradle.kts) выражает то же самое с типобезопасными аксессорами:
plugins {
java
}
dependencies {
implementation("com.google.guava:guava:33.0.0-jre")
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
}Задачи как единица работы
Всё, что делает Gradle, — это задача: compileJava, test, jar, build. Задачи объявляют зависимости от других задач, образуя направленный ациклический граф (DAG). Когда вы запускаете gradle build, Gradle обходит этот граф и выполняет каждое предусловие ровно один раз в нужном порядке. Вы также можете определять собственные задачи:
task hello {
doLast {
println 'Hello from a custom Gradle task'
}
}
task release {
dependsOn 'build', 'hello'
}Плагин java автоматически выстраивает стандартный граф: classes зависит от compileJava и processResources; jar зависит от classes; test зависит от classes и compileTestJava; build зависит от jar и test. Таким образом, запрос build выполняет все задачи в порядке зависимостей.
Обёртка и командная строка
Gradle Wrapper (gradlew / gradlew.bat) — это встроенный в проект скрипт, который загружает и запускает именно ту версию Gradle, которую ожидает проект, так что участникам не нужно устанавливать Gradle глобально:
./gradlew build # compile, test, and package
./gradlew test # run tests only
./gradlew clean build # wipe outputs, then rebuild from scratch
./gradlew tasks # list available tasks
./gradlew dependencies # print the resolved dependency treeИспользование ./gradlew вместо системного gradle является рекомендуемым стандартом — это делает сборку воспроизводимой на любых машинах и в CI.
Практический пример: граф задач, разрешённый как в Gradle
На этой странице нет Gradle, поэтому вместо реальной сборки мы моделируем основной движок Gradle на чистом Java: граф задач с зависимостями, разрешаемый в порядок выполнения с помощью топологической сортировки — именно это делает Gradle, когда вы вводите gradle build. Второй проход показывает, как актуальные задачи пропускаются, что и является инкрементальной сборкой Gradle.
Что можно вынести из запуска:
- Сборка объявляет 7 задач, но вы никогда не указываете порядок вручную — вы запрашиваете
build, а граф вычисляет остальное. Эта инверсия (объявляй зависимости, позволь инструменту упорядочить) — суть модели задач Gradle. - Разрешённый порядок выводит сначала
compileJavaиprocessResources, затемclasses,jar,compileTestJava,testи наконецbuild. Задача запускается только после всех задач, от которых зависит, — именно поэтому компиляция предшествует упаковке, а тесты —build. classesдостигается через два пути (черезjarи черезtest), но появляется в порядке один раз — множествоdoneгарантирует, что каждая задача выполняется единожды, точно так же как Gradle никогда не перекомпилирует одни и те же источники дважды в одном вызове.- При втором запуске три задачи, помеченные как актуальные, выводят
(UP-TO-DATE)и не засчитываются; толькоjar,compileTestJava,testиbuildпоказывают(EXEC). Это и есть инкрементальная сборка Gradle: задачи, входные данные которых не изменились, пропускаются. - Итоговая строка сообщает о выполнении
4 из 7задач. Пропуск неизменённой работы — именно поэтому второй запускgradle buildзначительно быстрее первого, и именно поэтому кеш сборки важен в крупных проектах.
Что охватывает остальная часть этого раздела
Написание реальных скриптов build.gradle, объявление и разрешение зависимостей из Maven Central, применение и настройка плагинов, определение пользовательских задач и использование обёртки в CI. Следующая глава, Сборка проекта Java с Gradle, настраивает полноценный проект Java с Gradle с нуля.