W3docs

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:

AspettoMavenGradle
File di buildpom.xml (XML)build.gradle (Groovy) o build.gradle.kts (Kotlin)
ModelloFasi del ciclo di vita fisseGrafo di task configurabile (un DAG)
EstensibilitàPlugin, legati alle fasiPlugin e task ad-hoc scritti inline
Build incrementaliLimitatoDi prima classe: controlli up-to-date + cache di build
Wrapperopzionalegradlew è la norma — fissa la versione di Gradle
VerbositàPiù boilerplateConciso, 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 taskcompileJava, 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 tree

Usare ./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.

java— editable, runs on the server

Cosa ricavare dall'esecuzione:

  • La build dichiara 7 task, ma non si specifica mai un ordine a mano — si chiede build e 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 compileJava e processResources, poi classes, jar, compileTestJava, test e infine build. Un task viene eseguito solo dopo ogni task da cui dipende, motivo per cui la compilazione precede il packaging e i test precedono build.
  • classes viene raggiunto attraverso due percorsi (via jar e via test) eppure appare una volta nell'ordine — il set done garantisce 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; solo jar, compileTestJava, test e build mostrano (EXEC). Questa è la build incrementale di Gradle: i task i cui input non sono cambiati vengono saltati.
  • La riga finale riporta 4 of 7 task eseguiti. Saltare il lavoro invariato è esattamente il motivo per cui un secondo gradle 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.

Esercitazione

Pratica
Quando esegui 'gradle build', come decide Gradle l'ordine in cui vengono eseguiti task come compileJava, test e jar?
Quando esegui 'gradle build', come decide Gradle l'ordine in cui vengono eseguiti task come compileJava, test e jar?
Was this page helpful?