Differenze tra dependanceManagement e dipendenze in Maven


768

Qual è la differenza tra dependencyManagemente dependencies? Ho visto i documenti sul sito web Apache Maven. Sembra che una dipendenza definita in dependencyManagementpuò essere utilizzata nei suoi moduli figlio senza specificare la versione.

Per esempio:

Un progetto principale (Pro-par) definisce una dipendenza in base a dependencyManagement:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8</version>
    </dependency>
 </dependencies>
</dependencyManagement>

Quindi nel figlio di Pro-par, posso usare la junit:

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
    </dependency>
 </dependencies>

Tuttavia, mi chiedo se è necessario definire junit nel pom genitore? Perché non definirlo direttamente nel modulo necessario?

Risposte:


464

La gestione delle dipendenze consente di consolidare e centralizzare la gestione delle versioni delle dipendenze senza aggiungere dipendenze ereditate da tutti i figli. Ciò è particolarmente utile quando si dispone di una serie di progetti (ovvero più di uno) che eredita un genitore comune.

Un altro caso d'uso estremamente importante dependencyManagementè il controllo delle versioni degli artefatti utilizzati nelle dipendenze transitive. Questo è difficile da spiegare senza un esempio. Fortunatamente, questo è illustrato nella documentazione.


17
Quindi, è necessario dichiarare le dipendenze nei pom del progetto figlio anche se hanno dichiarato nel pom del progetto genitore nella sezione <dependencyManagement>? È possibile creare una sorta di eredità delle dipendenze?
johnny-b-goode,

55
Sì, è ancora necessario definirli nel POM figlio per dimostrare che li si sta utilizzando. In realtà non sono inclusi nei progetti figlio solo perché si trovano nel <dependencyManagement>POM padre. Racchiudere le dipendenze nella <dependencyManagement>gestione centralizzata della versione, dell'ambito e delle esclusioni per ciascuna dipendenza, se e quando si decide di utilizzarla. La guida di Maven alla gestione delle dipendenze entra in tutti i dettagli.
hotshot309,

2
Il secondo paragrafo ( dependencyManagementcontrolla anche le dipendenze transitive) è vero solo quando le dipendenze sono impostate esplicitamente: stackoverflow.com/questions/28312975/…
Robert Metzger,

2
@ johnny-b-goode Quello che puoi ancora fare è creare una nuova dependenciessezione nel tuo genitore. Lo abbiamo fatto in modo che tutti i progetti figlio abbiano alcuni apache-commons di default e non li dichiarino sempre.
рüффп,

771

Sono alla moda in ritardo a questa domanda, ma penso che valga una risposta più chiara di quella accettata (che è corretta, ma non enfatizza la parte importante effettiva, che devi dedurre).

Nella POM principale, la differenza principale tra <dependencies>e <dependencyManagement>è questa:

Gli artefatti specificati nella <dependencies>sezione saranno SEMPRE inclusi come dipendenza dei moduli figlio.

Gli artefatti specificati nella <dependencyManagement>sezione, saranno inclusi nel modulo figlio solo se sono stati specificati anche nella <dependencies>sezione del modulo figlio stesso. Perché è bello chiedere? perché specifichi la versione e / o l'ambito nel genitore e puoi lasciarli fuori quando si specificano le dipendenze nel POM figlio. Questo può aiutarti a utilizzare le versioni unificate per le dipendenze per i moduli figlio, senza specificare la versione in ciascun modulo figlio.


1
Ma non è anche un po 'un overhead, usando <dependencyManagement>over <dependencies>nella radice .pom? I bambini pompotrebbero essere molto più brevi.
Janez Kuhar,

18
È vero. L'uso di <dipendenze> invece di <dependencyManagement> creerà un figlio minore. Tuttavia, ha un costo: significa che tali dipendenze saranno SEMPRE definite per TUTTI i moduli figlio. Se solo ALCUNI dei moduli figlio hanno bisogno di una certa dipendenza, invece di usare "<dependencyManagement>" ti permetterebbe di scegliere quali moduli figlio avranno quella dipendenza, ed essere comunque un po 'efficiente impostando la versione della dipendenza solo nel pom padre.
dcoder

2
@JanezKuhar Per me ha senso che se specifichi una dipendenza nel modulo figlio, questa avrà la precedenza su quella del genitore, ma ammetto di non ricordare. Dovrò controllare i documenti di Maven per quello quando avrò la possibilità. Anche se potrebbe essere più semplice impostare un semplice progetto genitore-figlio e verificare :)
dcoder

26
Buona spiegazione per un concetto semplice - perché sembra così difficile per Maven spiegare il proprio strumento così facilmente?
jimmy_terra,

1
Vorrei aggiungere Artifacts specified in the <dependencies> section will ALWAYS be included as a dependency of the child module(s)che sono inclusi anche nel genitore. Sembra che non sia possibile impostare una dipendenza per i bambini, ma non per il genitore.
caduceo

54

La documentazione sul sito Maven è orribile. Ciò che fa dependencyManagement è semplicemente spostare le definizioni delle dipendenze (versione, esclusioni, ecc.) Sul pom principale, quindi nei pom secondari devi solo inserire groupId e artefactId. Questo è tutto (tranne che per il concatenamento di pom padre e simili, ma non è nemmeno molto complicato - dependencyManagement vince sulle dipendenze a livello genitore - ma se hai una domanda su questo o le importazioni, la documentazione di Maven è un po 'migliore).

Dopo aver letto tutta la spazzatura "a", "b", "c" sul sito Maven e essermi confuso, ho riscritto il loro esempio. Quindi, se avessi 2 progetti (proj1 e proj2) che condividono una dipendenza comune (betaShared), potresti spostare quella dipendenza sul padre principale. Mentre ci sei, puoi anche spostare qualsiasi altra dipendenza (alfa e charlie) ma solo se ha senso per il tuo progetto. Quindi, per la situazione descritta nelle frasi precedenti, ecco la soluzione con dipendenzaGestione nel pom principale:

<!-- ParentProj pom -->
<project>
  <dependencyManagement>
    <dependencies>
      <dependency> <!-- not much benefit defining alpha here, as we only use in 1 child, so optional -->
        <groupId>alpha</groupId>
        <artifactId>alpha</artifactId>
        <version>1.0</version>
        <exclusions>
          <exclusion>
            <groupId>zebra</groupId>
            <artifactId>zebra</artifactId>
          </exclusion>
        </exclusions>
      </dependency>
      <dependency>
        <groupId>charlie</groupId> <!-- not much benefit defining charlie here, so optional -->
        <artifactId>charlie</artifactId>
        <version>1.0</version>
        <type>war</type>
        <scope>runtime</scope>
      </dependency>
      <dependency> <!-- defining betaShared here makes a lot of sense -->
        <groupId>betaShared</groupId>
        <artifactId>betaShared</artifactId>
        <version>1.0</version>
        <type>bar</type>
        <scope>runtime</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
</project>

<!-- Child Proj1 pom -->
<project>
  <dependencies>
    <dependency>
      <groupId>alpha</groupId>
      <artifactId>alpha</artifactId>  <!-- jar type IS DEFAULT, so no need to specify in child projects -->
    </dependency>
    <dependency>
      <groupId>betaShared</groupId>
      <artifactId>betaShared</artifactId>
      <type>bar</type> <!-- This is not a jar dependency, so we must specify type. -->
    </dependency>
  </dependencies>
</project>

<!-- Child Proj2 -->
<project>
  <dependencies>
    <dependency>
      <groupId>charlie</groupId>
      <artifactId>charlie</artifactId>
      <type>war</type> <!-- This is not a jar dependency, so we must specify type. -->
    </dependency>
    <dependency>
      <groupId>betaShared</groupId> 
      <artifactId>betaShared</artifactId> 
      <type>bar</type> <!-- This is not a jar dependency, so we must specify type. -->
    </dependency>
  </dependencies>
</project>

2
Domanda alquanto fuori tema: cosa significa "barra" del tipo di dipendenza? Ho visto in un esempio la documentazione di Maven ma non sono riuscito a trovare una definizione. Ho pensato che fosse un refuso di "guerra" o "vaso", ma lo vedo in altri esempi come il tuo.
NobodyMan,

NobodyMan - Quindi è solo un segnaposto per un altro tipo di archivio. Come usare "pippo". Oppure potrebbe essere usato se qualcuno ha creato un tipo personalizzato con l'estensione 'bar'. E ci sono molti tipi di archivi oscuri là fuori. Come sar, che è l'archivio del servizio jboss.
MattC

Il tuo esempio è abbastanza chiaro e ribadisce ciò che avevo sgridato da solo dalla documentazione. L'hai inviato al progetto Maven? Dopo aver studiato il tuo esempio, mi sto preparando a semplificare un POM che ha entrambi e necessita solo di dichiarazioni di dipendenza, poiché il progetto al quale è associato non ha figli.
David A. Gray,

Bene, stavo per abbandonare il nodo DependencyManagement, fino a quando non mi è venuto in mente che lasciarlo mi permettesse di stabilire una versione minima per qualsiasi figlio POM che trovasse indirettamente l'albero delle dipendenze. Ad esempio, inseguendo javax.cache.cache-apI, ho scoperto una versione significativamente più recente 1.0.0 (rispetto a 0.3.0) che può anche essere utilizzata in tutto.
David A. Gray,

Questa spiegazione è perfetta.
Smart Coder

45

È come hai detto tu; dependencyManagementviene utilizzato per estrarre tutte le informazioni sulla dipendenza in un file POM comune, semplificando i riferimenti nel file POM figlio.

Diventa utile quando hai più attributi in cui non vuoi riscrivere in più progetti figlio.

Infine, dependencyManagementpuò essere utilizzato per definire una versione standard di un artefatto da utilizzare su più progetti.


4
Quindi, le dipendenze non ereditano? Bisogna comunque dichiararlo nel pom del progetto figlio?
johnny-b-goode,

6
Sì, è necessario dichiararli comunque nei progetti figlio, ma senza specificare una versione.
Pavel Vlasov,

Questo scenario è utile quando si desidera avere la governance delle versioni in più progetti Java con relazione padre-figlio.
Anuj Kumar,

43

C'è ancora una cosa che non è abbastanza evidenziata, secondo me, e che è l'eredità indesiderata .

Ecco un esempio incrementale:

Dichiaro nel mio parentpom:

<dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>19.0</version>
        </dependency>
</dependencies>

boom! Ce l'ho nel mio Child A, Child Be Child Cmoduli:

  • Implicility ereditata dai figli del bambino
  • Un unico posto da gestire
  • Non è necessario dichiarare nulla nei poms per bambini
  • Posso ancora rielaborare e sovrascrivere version 18.0in un Child Bse lo desidero.

Ma cosa succede se finisco per non aver bisogno della guava Child C, e nemmeno in futuro Child De nei Child Emoduli?

Lo erediteranno ancora e questo è indesiderato! Questo è proprio come l'odore del codice di God God Object, in cui erediti alcuni bit utili da una classe e anche un sacco di cose indesiderate.

È qui che <dependencyManagement>entra in gioco. Quando aggiungi questo al tuo genitore, tutti i tuoi moduli figlio smettono di vederlo . E così sei costretto a entrare in ogni singolo modulo che ne ha bisogno e dichiararlo di nuovo ( Child Ae Child B, senza la versione però).

E, ovviamente, non lo fai per Child C, e quindi il tuo modulo rimane snello.


Le dipendenze menzionate in <dependencyManagement> verranno scaricate per il progetto pom padre?
Jaspreet Jolly

Sei sicuro che se usiamo <dependencyManagement>nel padre pom allora le dipendenze di default non saranno ereditate nei pon pon figlio? Perché nel documento: maven.apache.org/guides/introduction/… mentre si spiega il secondo uso di <dependencyManagement>esso sembra che sarà ereditato per impostazione predefinita. Ad un certo punto stanno dicendo che: "Quando maven viene eseguito sul progetto B, verrà utilizzata la versione 1.0 degli artefatti a, b, c e d indipendentemente dalla versione specificata nel loro pom" anche se "b" non è usato in il progetto B
chirag soni,

Provalo tu stesso
Andrejs,

17

Ci sono alcune risposte che delineano le differenze tra <depedencies>e <dependencyManagement>tag con maven.

Tuttavia, alcuni punti elaborati di seguito in modo conciso:

  1. <dependencyManagement>consente di consolidare tutte le dipendenze (utilizzate a livello di pom figlio) utilizzate in diversi moduli: chiarezza , gestione centralizzata della versione delle dipendenze
  2. <dependencyManagement>consente di aggiornare / declassare facilmente le dipendenze in base alle necessità, in altri scenari questo deve essere esercitato a tutti i livelli del bambino - coerenza
  3. le dipendenze fornite nel <dependencies>tag vengono sempre importate, mentre le dipendenze fornite <dependencyManagement>nel pom principale verranno importate solo se il figlio pom ha la relativa voce nel suo <dependencies>tag.

17

Scusa, sono in ritardo alla festa.

Vorrei provare a spiegare la differenza usando il mvn dependency:treecomando

Considera l'esempio seguente

Parent POM - Il mio progetto

<modules>
    <module>app</module>
    <module>data</module>
</modules>

<dependencies>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>19.0</version>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
        </dependency>
    </dependencies>
</dependencyManagement>

Child POM - modulo dati

<dependencies>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
    </dependency>
</dependencies>

POM figlio - modulo app (non ha dipendenze extra, quindi lascia le dipendenze vuote)

 <dependencies>
</dependencies>

Su mvn dependency:treecomando in esecuzione , otteniamo il seguente risultato

Scanning for projects...
------------------------------------------------------------------------
Reactor Build Order:

MyProject
app
data

------------------------------------------------------------------------
Building MyProject 1.0-SNAPSHOT
------------------------------------------------------------------------

--- maven-dependency-plugin:2.8:tree (default-cli) @ MyProject ---
com.iamvickyav:MyProject:pom:1.0-SNAPSHOT
\- com.google.guava:guava:jar:19.0:compile

------------------------------------------------------------------------
Building app 1.0-SNAPSHOT
------------------------------------------------------------------------

--- maven-dependency-plugin:2.8:tree (default-cli) @ app ---
com.iamvickyav:app:jar:1.0-SNAPSHOT
\- com.google.guava:guava:jar:19.0:compile

------------------------------------------------------------------------
Building data 1.0-SNAPSHOT
------------------------------------------------------------------------

--- maven-dependency-plugin:2.8:tree (default-cli) @ data ---
com.iamvickyav:data:jar:1.0-SNAPSHOT
+- org.apache.commons:commons-lang3:jar:3.9:compile
\- com.google.guava:guava:jar:19.0:compile

Google guava è elencato come dipendenza in ogni modulo (incluso il genitore), mentre i beni comuni apache sono elencati come dipendenza solo nel modulo dati (nemmeno nel modulo genitore)


11

Se la dipendenza era definita nell'elemento dependencyManagement di pom di livello superiore, il progetto figlio non doveva elencare esplicitamente la versione della dipendenza. se il progetto figlio avesse definito una versione, avrebbe la precedenza sulla versione elencata nella sezione Gestione delle dipendenze di POM di livello superiore. In altre parole, la versione dependencyManagement viene utilizzata solo quando il figlio non dichiara direttamente una versione.


1
Credo che questa affermazione potrebbe non essere corretta. Negli esempi di gestione delle dipendenze di Maven (n. 2), si dice che le dipendenze definite in un pom padre con una versione, sovrascriveranno la versione specificata nel figlio secondario: "Quando il maven viene eseguito sul progetto B versione 1.0 degli artefatti a, b, c e d verranno utilizzati indipendentemente dalla versione specificata nel loro pom. "
Devdanke,

@devdanke Almeno, problemi di Eclipse M2E un avvertimento: imperativi gestito versione ... per ... .
GeroldBroser ripristina Monica il

4

Nella POM principale, la differenza principale tra <dependencies>e <dependencyManagement>è questa:

Gli artefatti specificati nella <dependencies>sezione saranno SEMPRE inclusi come dipendenza dei moduli figlio.

Gli artefatti specificati nella sezione, saranno inclusi nel modulo figlio solo se sono stati specificati anche nella sezione del modulo figlio stesso. Perché è bello chiedere? perché specifichi la versione e / o l'ambito nel genitore e puoi lasciarli fuori quando si specificano le dipendenze nel POM figlio. Questo può aiutarti a utilizzare le versioni unificate per le dipendenze per i moduli figlio, senza specificare la versione in ciascun modulo figlio.


4

Solo con le mie stesse parole, ti parent-projectaiuta a fornire 2 tipi di dipendenze:

  • dipendenze implicite : tutte le dipendenze definite nella <dependencies>sezione nella tua parent-projectsono ereditate da tutte lechild-projects
  • dipendenze esplicite : consente di selezionare le dipendenze da applicare nel proprio child-projects. Pertanto, si utilizza la <dependencyManagement>sezione per dichiarare tutte le dipendenze che si intende utilizzare nelle diverse child-projects. La cosa più importante è che, in questa sezione, si definisce un in <version>modo da non doverlo dichiarare di nuovo nel proprio child-project.

Il <dependencyManagement>mio punto di vista (correggimi se sbaglio) è utile solo per aiutarti a centralizzare la versione delle tue dipendenze. È come una sorta di funzione di supporto.


1

In Eclipse, c'è un'altra funzione in dependencyManagement. Quando dependenciesviene utilizzato senza di essa, le dipendenze infondate vengono rilevate nel file pom. Se dependencyManagementviene utilizzato, le dipendenze irrisolte rimangono inosservate nel file pom e gli errori vengono visualizzati solo nei file java. (importazioni e simili ...)


1

La differenza tra i due è meglio portata in quella che sembra una definizione necessaria e sufficiente dell'elemento dependencyManagement disponibile nei documenti del sito Web Maven:

dependencyManagement

"Informazioni di dipendenza predefinite per i progetti che ereditano da questo. Le dipendenze in questa sezione non vengono immediatamente risolte. Invece, quando un POM derivato da questo dichiara una dipendenza descritta da un ID gruppo e un artefatto corrispondenti, la versione e altri valori di questa sezione vengono utilizzati per tale dipendenza se non sono già stati specificati. " [ https://maven.apache.org/ref/3.6.1/maven-model/maven.html ]

Dovrebbe essere letto insieme ad alcune ulteriori informazioni disponibili su una pagina diversa:

“.. l'insieme minimo di informazioni per abbinare un riferimento di dipendenza a una sezione di gestione delle dipendenze è in realtà {groupId, artefactId, type, classifier}. In molti casi, queste dipendenze faranno riferimento a artefatti jar senza classificatore. Questo ci consente di abbreviare l'identità impostata su {groupId, artefactId}, poiché il valore predefinito per il campo type è jar e il classificatore predefinito è null. " [ https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html ]

Pertanto, tutti gli elementi secondari (ambito, esclusioni ecc.) Di un elemento di dipendenza - diversi da groupId, artefactId, tipo, classificatore, non solo versione - sono disponibili per il blocco / default nel punto (e quindi ereditati da in seguito) si specifica la dipendenza all'interno di un dependencyElement. Se avessi specificato una dipendenza con gli elementi secondari di tipo e classificatore (vedi la pagina Web citata per primo per controllare tutti gli elementi secondari) rispettivamente come non jar e non null, avresti bisogno di {groupId, artefactId, classifier, type} per fare riferimento (risolvere) tale dipendenza in qualsiasi punto di un'eredità originata dall'elemento dependencyManagement. Altrimenti, {groupId, artifactId} sarebbe sufficiente se non si intende sostituire i valori predefiniti per classificatore e tipo (rispettivamente jar e null). Quindi default è una buona parola chiave in quella definizione; tutti gli elementi secondari (diversi da groupId,

Quindi, qualsiasi elemento di dipendenza al di fuori di dependencyManagement, sia come riferimento ad un elemento dependencyManagement o come standalone, viene immediatamente risolto (cioè installato nel repository locale e disponibile per i percorsi di classe).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.