Introduzione a Gradle per Java
Cosa è Gradle, come si confronta con Maven e come configurare un progetto Java con Gradle.
Gradle è uno strumento di automazione della build per la JVM (e non solo) che compila il codice, esegue i test, gestisce le dipendenze e impacchetta il risultato — tutto guidato da uno script di build scritto in Groovy o Kotlin. Dove Maven descrive un progetto con XML fisso, Gradle lo descrive con codice: uno script di build che configura un grafo di task. Questo passaggio a un modello programmabile, unito a una cache di build incrementale che salta il lavoro già eseguito, è il motivo per cui Gradle alimenta Android e molti grandi progetti Java.
Gradle vs. Maven
Entrambi gli strumenti risolvono lo stesso problema — build ripetibili con dipendenze gestite — ma fanno scelte diverse. Se conosci già Maven, questa è la mappa:
| Aspetto | Maven | Gradle |
|---|---|---|
| File di build | pom.xml (XML) | build.gradle (Groovy) o build.gradle.kts (Kotlin) |
| Modello | Fasi del ciclo di vita fisse | Grafo di task configurabile (un DAG) |
| Estensibilità | Plugin, legati alle fasi | Plugin e task ad-hoc scritti inline |
| Build incrementali | Limitato | Di prima classe: controlli up-to-date + cache di build |
| Wrapper | opzionale | gradlew è la norma — fissa la versione di Gradle |
| Verbosità | Più boilerplate | Conciso, ma più "magia" da imparare |
Nessuno dei due è strettamente migliore. La rigidità di Maven rende le build prevedibili; la flessibilità di Gradle rende esprimibili le build complesse. Questa parte insegna Gradle; l'introduzione a Maven copre l'altro lato.
Uno script di build Java minimale
Un progetto Gradle Java è un build.gradle più un layout sorgente convenzionale (src/main/java, src/test/java). L'applicazione del plugin java integrato è ciò che insegna a Gradle come compilare, testare e creare il 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'
}Il Kotlin DSL (build.gradle.kts) esprime la stessa cosa con accessor type-safe:
plugins {
java
}
dependencies {
implementation("com.google.guava:guava:33.0.0-jre")
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
}I task sono l'unità di lavoro
Tutto ciò che Gradle fa è un task — compileJava, test, jar, build. I task dichiarano dipendenze da altri task, formando un grafo aciclico diretto (DAG). Quando esegui gradle build, Gradle percorre quel grafo ed esegue ogni prerequisito esattamente una volta, in ordine. Puoi anche definire i tuoi:
task hello {
doLast {
println 'Hello from a custom Gradle task'
}
}
task release {
dependsOn 'build', 'hello'
}Il plugin java crea un grafo standard per te: classes dipende da compileJava e processResources; jar dipende da classes; test dipende da classes e compileTestJava; e build dipende da jar e test. Richiedere build esegue quindi tutti nell'ordine delle dipendenze.
Il wrapper e la riga di comando
Il Gradle Wrapper (gradlew / gradlew.bat) è uno script incluso nel repository che scarica ed esegue la versione esatta di Gradle che un progetto si aspetta, in modo che i collaboratori non abbiano bisogno di Gradle installato globalmente:
./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 treeUsare ./gradlew invece di un gradle di sistema è il default consigliato — rende la build riproducibile su macchine diverse e in CI.
Un esempio pratico: un grafo di task, risolto come fa Gradle
Non è disponibile Gradle nel runner di questa pagina, quindi invece di una vera build modelliamo il motore core di Gradle in Java puro: un grafo di task con dipendenze, risolto in un ordine di esecuzione con un ordinamento topologico — esattamente quello che fa Gradle quando digiti gradle build. Il secondo passaggio mostra come i task up-to-date vengono saltati, che è il trucco di Gradle per le build incrementali.
Cosa ricavare dall'esecuzione:
- La build dichiara 7 task, ma non si specifica mai un ordine a mano — si chiede
builde il grafo calcola il resto. Quella inversione (dichiarare le dipendenze, lasciare che lo strumento le ordini) è il cuore del modello di task di Gradle. - L'ordine risolto stampa prima
compileJavaeprocessResources, poiclasses,jar,compileTestJava,teste infinebuild. Un task viene eseguito solo dopo ogni task da cui dipende, motivo per cui la compilazione precede il packaging e i test precedonobuild. classesviene raggiunto attraverso due percorsi (viajare viatest) eppure appare una volta nell'ordine — il setdonegarantisce che ogni task venga eseguito una sola volta, proprio come Gradle non ricompila mai le stesse sorgenti due volte in una singola invocazione.- Al secondo run, i tre task contrassegnati come up-to-date stampano
(UP-TO-DATE)e non vengono conteggiati; solojar,compileTestJava,testebuildmostrano(EXEC). Questa è la build incrementale di Gradle: i task i cui input non sono cambiati vengono saltati. - La riga finale riporta
4 of 7task eseguiti. Saltare il lavoro invariato è esattamente il motivo per cui un secondogradle buildè molto più veloce del primo e perché la cache di build è importante nei grandi progetti.
Cosa copre il resto di questa parte
Scrivere script build.gradle reali, dichiarare e risolvere dipendenze da Maven Central, applicare e configurare plugin, definire task personalizzati e usare il wrapper in CI. Il prossimo capitolo, Costruire un progetto Java con Gradle, configura un progetto Gradle Java completo partendo da una directory vuota.