[JAVA] À propos de la compilation, de l'API, de l'implémentation, etc. de Gradle

Une note d'étude sur compile, ʻapi, ʻimplementation spécifiée par dependencies dans Gradle.

compile est obsolète

Java Library Plugin a été ajouté dans Gradle 3.4 (https://docs.gradle.org/3.4/release-notes. (html # the-java-library-plugin), il semble que l'utilisation de compile with dependencies était obsolète (aussi runtime, testCompile, testRuntime).

Dans 4.7 Description du plug-in Java, il est écrit comme obsolète. (Documentation 4.6 ne dit pas «obsolète», mais c'est définitivement obsolète Récemment?)

Il est recommandé d'utiliser ʻimplementation et ʻapi à la place.

Différence entre compilation et implémentation

Pour compiler

La mise en oeuvre

Structure du projet


|-settings.gradle
|-build.gradle
|
|-foo/
|  |-build.gradle
|  `-src/main/java/foo/
|    `-Foo.java
|
`-bar/
   |-build.gradle
   `-src/main/java/bar/
     `-Bar.java

/settings.gradle


include 'foo', 'bar'

/build.gradle


subprojects {
    apply plugin: 'java'

    sourceCompatibility = 10
    targetCompatibility = 10

    compileJava.options.encoding = 'UTF-8'

    repositories {
        mavenCentral()
    }
}

/bar/build.gradle


dependencies {
    compile 'org.apache.commons:commons-lang3:3.7'
}

Bar.java


package bar;

import org.apache.commons.lang3.RandomStringUtils;

public class Bar {

    public void hello() {
        System.out.println("Bar: " + RandomStringUtils.random(10, "0123456789"));
    }
}

/foo/build.gradle


apply plugin: 'application'

mainClassName = 'foo.Foo'

dependencies {
    compile project(':bar')
}

Foo.java


package foo;

import bar.Bar;
import org.apache.commons.lang3.RandomStringUtils;

public class Foo {

    public static void main(String... args) {
        new Bar().hello();
        System.out.println("Foo: " + RandomStringUtils.random(10, "0123456789"));
    }
}

--Comprend deux sous-projets, foo et bar --bar dépend de commons-lang3 --foo dépend du projet bar --Chaque projet utilise commons-lang3

** Résultat d'exécution **

> gradle :foo:run
Bar: 3803159716
Foo: 6423224304

Lors de l'utilisation de l'implémentation

La mise en oeuvre

/bar/build.gradle


dependencies {
    implementation 'org.apache.commons:commons-lang3:3.7'
}

/foo/build.gradle


apply plugin: 'application'

mainClassName = 'foo.Foo'

dependencies {
    implementation project(':bar')
}

** Résultat d'exécution **

> gradle :foo:run

...\foo\src\main\java\foo\Foo.java:4:Erreur:Organisation du package.apache.commons.lang3 n'existe pas
import org.apache.commons.lang3.RandomStringUtils;
                               ^
...\foo\src\main\java\foo\Foo.java:10:Erreur:Impossible de trouver le symbole
        System.out.println("Foo: " + RandomStringUtils.random(10, "0123456789"));
                                     ^
symbole:Variable RandomStringUtils
endroit:Classe Foo
2 erreurs

...

La description

Relation de dépendance


# compile
[foo] --compile--> [bar] --compile--> [commons-lang3]

  [foo] - ok -> [bar] - ok -> [commons-lang3]
    |                               ^
    |                               |
    +------------ ok ---------------+

# implementation
[foo] --implementation--> [bar] --implementation--> [commons-lang3]

  [foo] - ok -> [bar] - ok -> [commons-lang3]
    |                               x
    |                               |
    +------------ ng ---------------+

--La dépendance spécifiée par compile est propagée

Propager les dépendances

La mise en oeuvre

/bar/build.gradle


apply plugin: 'java-library'

dependencies {
    api 'org.apache.commons:commons-lang3:3.7'
}

** Résultat d'exécution **

$ gradle :foo:run

Bar: 7783742303
Foo: 6741510207

La description

/bar/build.gradle


apply plugin: 'java-library'

dependencies {
    api 'org.apache.commons:commons-lang3:3.7'
}

--Pour propager des dépendances comme compile, spécifiez les dépendances avec ʻapi --ʻApi devient disponible en ajoutant Java Library Plugin

mérite

La documentation officielle explique que l'utilisation de ʻimplementation au lieu de compiler` présente les avantages suivants:

  1. Les dépendances ne sont divulguées nulle part côté utilisateur au moment de la compilation. Par conséquent, les dépendances transitoires involontaires ne se produisent pas.
  2. Le chemin de classe supprimé accélère la compilation.
  3. Même si la dépendance spécifiée dans ʻimplementation` est modifiée, l'utilisateur n'a pas besoin de recompiler.
  4. Lorsqu'il est utilisé en combinaison avec le nouveau plug-in Maven, il génère un fichier POM qui sépare clairement les bibliothèques requises au moment de la compilation et les bibliothèques requises au moment de l'exécution, et peut être publié proprement (honnêtement, plug-in Maven). Je ne l'utilise pas donc je ne suis pas sûr)

En bref, l'utilisation de compile posait les problèmes suivants.

―― Puisque toutes les dépendances sont propagées de manière transitoire, les dépendances se sont étendues inutilement.

En définissant cela avec ʻimplementation, il est possible d'empêcher l'expansion inutile des dépendances et de ne faire la transition que les dépendances qui sont vraiment nécessaires avec ʻapi.

Il y a aussi l'avantage que la fréquence de recompilation peut être réduite en empêchant la "mise en œuvre" de propager des dépendances.

Utilisation correcte de «mise en œuvre» et «api»

Voici mon opinion personnelle.

--Déclaré de manière basique avec ʻimplementation --Publiez côté utilisateur avec ʻapi seulement quand il est absolument nécessaire de le propager côté utilisateur ――Si possible, je pense que ce serait mieux si vous pouviez éliminer la dépendance directe à la bibliothèque que vous utilisez en l'enveloppant dans votre propre API. --Facile à remplacer les bibliothèques

Résumé

configuration Propagation des dépendances Plug-in défini
compile Faire Java Plugin
implementation ne pas faire Java Plugin
api Faire Java Library Plugin

référence

Recommended Posts

À propos de la compilation, de l'API, de l'implémentation, etc. de Gradle
Mâchez l'API
À propos de l'API Apache Inference
À propos de l'implémentation du traitement de fusion, y compris la fonction de tri de l'API Stream
À propos de l'API d'ontologie Apache Jena