Διαχείριση εξαρτήσεων

7 λεπτά

Πίνακας περιεχομένων


1 — Τι είναι μια εξάρτηση;

Μια εξάρτηση είναι μια εξωτερική βιβλιοθήκη που χρειάζεται το έργο σας για να μεταγλωττιστεί ή να εκτελεστεί. Αντί να ξαναγράφετε κώδικα (ανάλυση JSON, πρόσβαση σε βάση δεδομένων, δοκιμές…), επαναχρησιμοποιείτε δοκιμασμένες βιβλιοθήκες.

Το Maven διαχειρίζεται αυτές τις εξαρτήσεις αυτόματα: τις δηλώνετε στο pom.xml και το Maven τις κατεβάζει και τις τοποθετεί στο classpath.

Χωρίς MavenΜε Maven
Χειροκίνητη λήψη κάθε .jarΔήλωση 3 γραμμών στο pom.xml
Χειροκίνητη διαχείριση του classpathΤο Maven το κατασκευάζει αυτόματα
Εύρεση συμβατών βιβλιοθηκώνΑυτόματη μεταβατική επίλυση

Μια εξάρτηση ταυτοποιείται επίσης από τις συντεταγμένες GAV (groupId:artifactId:version), ακριβώς όπως το δικό σας έργο. Έτσι ξέρει το Maven τι να κατεβάσει.

↑ Επιστροφή στην αρχή


2 — Δήλωση μιας εξάρτησης

Οι εξαρτήσεις δηλώνονται στο μπλοκ <dependencies> του pom.xml. Κάθε εξάρτηση είναι μια ετικέτα <dependency> με τις συντεταγμένες GAV της.

xml
<dependencies>

    <!-- Βιβλιοθήκη Gson της Google για χειρισμό JSON -->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.10.1</version>
    </dependency>

</dependencies>

Για να βρείτε τις σωστές συντεταγμένες μιας βιβλιοθήκης, συμβουλεύεστε το Maven Central (search.maven.org), που παρέχει το μπλοκ XML έτοιμο προς αντιγραφή.

bash
# Μετά την προσθήκη εξάρτησης, πυροδοτείτε τη λήψη
mvn compile

# Ή ρητή λήψη χωρίς μεταγλώττιση
mvn dependency:resolve
ΣτοιχείοΡόλος
<groupId>Ο οργανισμός που δημοσιεύει τη βιβλιοθήκη
<artifactId>Το όνομα της βιβλιοθήκης
<version>Η επιθυμητή έκδοση

Το Maven αποθηκεύει τις βιβλιοθήκες στην κρυφή μνήμη στο ~/.m2/repository. Μια ήδη ληφθείσα βιβλιοθήκη δεν ξανακατεβαίνει ποτέ: γι' αυτό οι επόμενες κατασκευές είναι γρήγορες.

🔧 Μίνι-άσκηση — Δηλώστε την εξάρτηση Gson (com.google.code.gson:gson:2.10.1) σε ένα μπλοκ <dependency>.

✅ Δείτε μια λύση
xml
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.10.1</version>
</dependency>

↑ Επιστροφή στην αρχή


3 — Τα πεδία εφαρμογής (scopes)

Το πεδίο εφαρμογής (scope) μιας εξάρτησης δηλώνει πότε και πού είναι διαθέσιμη: στη μεταγλώττιση, στις δοκιμές, στην εκτέλεση, ή παρέχεται από το περιβάλλον. Το προσδιορίζετε με <scope>.

xml
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.10.2</version>
    <scope>test</scope>   <!-- διαθέσιμη μόνο για τις δοκιμές -->
</dependency>
ScopeΔιαθέσιμη στη μεταγλώττισηΔιαθέσιμη στις δοκιμέςΔιαθέσιμη στην εκτέλεσηΠεριλαμβάνεται στο τεχνούργημα
compile (προεπιλογή)
test
provided❌ (την παρέχει ο διακομιστής)
runtime

Συγκεκριμένα παραδείγματα:

ΒιβλιοθήκηΤυπικό scopeΓιατί
JUnittestΧρήσιμη μόνο για την εκτέλεση των δοκιμών
API ServletprovidedΟ διακομιστής (Tomcat) την παρέχει ήδη
Οδηγός JDBCruntimeΑπαιτείται στην εκτέλεση, όχι στη μεταγλώττιση
GsoncompileΧρησιμοποιείται παντού στον κώδικα

Η τοποθέτηση του JUnit σε compile αντί για test είναι συχνό σφάλμα: ενσωματώνει άσκοπα τη βιβλιοθήκη δοκιμών στο τελικό παραδοτέο. Επιλέγετε πάντα το πιο περιοριστικό scope που ταιριάζει.

🔧 Μίνι-άσκηση — Δηλώστε μια εξάρτηση JUnit Jupiter (5.10.2) σε πεδίο εφαρμογής test στο pom.xml.

✅ Δείτε μια λύση
xml
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.10.2</version>
    <scope>test</scope>
</dependency>

↑ Επιστροφή στην αρχή


4 — Τα αποθετήρια (repositories)

Το Maven κατεβάζει τις εξαρτήσεις από αποθετήρια (repositories). Υπάρχουν τρία επίπεδα:

Τύπος αποθετηρίουΠεριγραφή
Τοπικό αποθετήριοΚρυφή μνήμη στον υπολογιστή σας: ~/.m2/repository
Maven CentralΤο παγκόσμιο δημόσιο αποθετήριο, προεπιλεγμένη πηγή
Ιδιωτικό αποθετήριοΔιακομιστής επιχείρησης (Nexus, Artifactory) για εσωτερικές βιβλιοθήκες

Για να προσθέσετε ένα ιδιωτικό αποθετήριο, το δηλώνετε στο pom.xml:

xml
<repositories>
    <repository>
        <id>nexus-entreprise</id>
        <url>https://nexus.monentreprise.com/repository/maven-public/</url>
    </repository>
</repositories>
bash
# Αναγκαστική ενημέρωση των εξαρτήσεων από τα αποθετήρια
mvn clean install -U

# Εκκαθάριση της κρυφής μνήμης μιας βιβλιοθήκης για να αναγκαστεί η εκ νέου λήψη
# (χειροκίνητη διαγραφή του αντίστοιχου φακέλου στο ~/.m2)
ΠερίπτωσηΑποθετήριο που χρησιμοποιείται
Δημόσια βιβλιοθήκη ανοιχτού κώδικαMaven Central
Εσωτερική βιβλιοθήκη της επιχείρησηςΙδιωτικό αποθετήριο (Nexus/Artifactory)
Ήδη ληφθείσα βιβλιοθήκηΤοπική κρυφή μνήμη ~/.m2

Οι επιχειρήσεις χρησιμοποιούν συχνά ένα ιδιωτικό αποθετήριο ως καθρέφτη του Maven Central: αυτό επιταχύνει τις λήψεις και επιτρέπει τον έλεγχο ποιων βιβλιοθηκών επιτρέπονται.

↑ Επιστροφή στην αρχή


5 — Η μεταβατική επίλυση

Μια εξάρτηση μπορεί η ίδια να εξαρτάται από άλλες βιβλιοθήκες: αυτές είναι οι μεταβατικές εξαρτήσεις. Το Maven τις κατεβάζει αυτόματα — δεν χρειάζεται να τις απαριθμήσετε.

Δηλώνετε μία εξάρτηση, το Maven επιλύει δεκάδες:

xml
<!-- Μία μόνο δήλωση... -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>3.2.5</version>
</dependency>
<!-- ...φέρνει αυτόματα spring-web, jackson, tomcat κ.λπ. -->

Για να απεικονίσετε το πλήρες δέντρο:

bash
# Εμφανίζει το δέντρο εξαρτήσεων (άμεσες + μεταβατικές)
mvn dependency:tree

Τυπική έξοδος:

com.exemple:mon-app:jar:1.0.0
+- org.springframework.boot:spring-boot-starter-web:jar:3.2.5:compile
|  +- org.springframework:spring-web:jar:6.1.6:compile
|  +- com.fasterxml.jackson.core:jackson-databind:jar:2.15.4:compile
|  \- org.apache.tomcat.embed:tomcat-embed-core:jar:10.1.20:compile

Όταν δύο διαδρομές φέρνουν δύο διαφορετικές εκδόσεις της ίδιας βιβλιοθήκης, το Maven εφαρμόζει τον κανόνα του «πλησιέστερου στο δέντρο» (nearest wins): κερδίζει η έκδοση που βρίσκεται πιο κοντά στο έργο σας.

Η μεταβατική επίλυση είναι μία από τις μεγαλύτερες δυνάμεις του Maven: δηλώνετε τις προθέσεις σας σε υψηλό επίπεδο και το Maven συναρμολογεί όλο το παζλ των εξαρτήσεων για εσάς.

🔧 Μίνι-άσκηση — Γράψτε την εντολή που εμφανίζει το πλήρες δέντρο εξαρτήσεων (άμεσες και μεταβατικές).

✅ Δείτε μια λύση
bash
mvn dependency:tree

↑ Επιστροφή στην αρχή


6 — Διάγνωση και αποκλεισμός

Μερικές φορές μια μεταβατική εξάρτηση δημιουργεί πρόβλημα (σύγκρουση έκδοσης, ανεπιθύμητη βιβλιοθήκη). Το Maven προσφέρει εργαλεία διάγνωσης και διόρθωσης.

Για να αποκλείσετε μια ανεπιθύμητη μεταβατική εξάρτηση:

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>3.2.5</version>
    <exclusions>
        <exclusion>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-to-slf4j</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Χρήσιμες εντολές διάγνωσης:

ΕντολήΡόλος
mvn dependency:treeΕμφανίζει το πλήρες δέντρο εξαρτήσεων
mvn dependency:analyzeΑνιχνεύει αχρησιμοποίητες ή ελλείπουσες εξαρτήσεις
mvn dependency:resolveΚατεβάζει όλες τις εξαρτήσεις
bash
# Εντοπισμός εξαρτήσεων που δηλώθηκαν αλλά δεν χρησιμοποιούνται,
# και εκείνων που χρησιμοποιούνται αλλά δεν δηλώθηκαν
mvn dependency:analyze

Πριν αποκλείσετε οτιδήποτε, εκτελέστε mvn dependency:tree για να κατανοήσετε από πού προέρχεται η προβληματική εξάρτηση. Ποτέ δεν αποκλείουμε στα τυφλά.

🔧 Μίνι-άσκηση — Γράψτε την εντολή που εντοπίζει τις δηλωμένες αλλά αχρησιμοποίητες εξαρτήσεις (και το αντίστροφο).

✅ Δείτε μια λύση
bash
mvn dependency:analyze

↑ Επιστροφή στην αρχή


7 — Κουίζ — Διαχείριση εξαρτήσεων

Question 1 : Πού αποθηκεύει το Maven στην κρυφή μνήμη τις ληφθείσες εξαρτήσεις;

a) Στο target/

b) Στο ~/.m2/repository

c) Στο src/main/resources

d) Στον διακομιστή ιστού

💡 Δείτε τη λύση

Απάντηση: b) — Το τοπικό αποθετήριο ~/.m2/repository λειτουργεί ως κρυφή μνήμη: μια ήδη ληφθείσα βιβλιοθήκη δεν ξανακατεβαίνει.


Question 2 : Ποιο scope ταιριάζει στο JUnit, βιβλιοθήκη που χρησιμοποιείται μόνο για τις δοκιμές;

a) compile

b) runtime

c) test

d) provided

💡 Δείτε τη λύση

Απάντηση: c) — Το scope test καθιστά την εξάρτηση διαθέσιμη μόνο στις δοκιμές και την αποκλείει από το τελικό παραδοτέο.


Question 3 : Τι είναι οι μεταβατικές εξαρτήσεις;

a) Εξαρτήσεις που πρέπει να απαριθμήσετε χειροκίνητα

b) Οι εξαρτήσεις των εξαρτήσεών σας, επιλυμένες αυτόματα από το Maven

c) Προσωρινές εξαρτήσεις

d) Εξαρτήσεις δοκιμών

💡 Δείτε τη λύση

Απάντηση: b) — Μια δηλωμένη εξάρτηση φέρνει τις δικές της εξαρτήσεις· το Maven τις κατεβάζει αυτόματα.


Question 4 : Ποια εντολή εμφανίζει το πλήρες δέντρο εξαρτήσεων;

a) mvn list

b) mvn dependency:tree

c) mvn show-deps

d) mvn package

💡 Δείτε τη λύση

Απάντηση: b) — Το mvn dependency:tree δείχνει τις άμεσες και μεταβατικές εξαρτήσεις, χρήσιμο για διάγνωση συγκρούσεων.


Question 5 : Ποιο scope να επιλέξετε για το API Servlet, που παρέχεται από τον διακομιστή Tomcat;

a) compile

b) test

c) provided

d) runtime

💡 Δείτε τη λύση

Απάντηση: c)provided: η βιβλιοθήκη χρειάζεται για τη μεταγλώττιση, αλλά το περιβάλλον εκτέλεσης (ο διακομιστής) την παρέχει ήδη.

↑ Επιστροφή στην αρχή


8 — Πρακτική — Προσθήκη εξαρτήσεων

Εκφώνηση

Σε ένα υπάρχον έργο, προσθέστε δύο εξαρτήσεις: Gson (com.google.code.gson:gson:2.10.1) σε πεδίο εφαρμογής compile για χειρισμό JSON, και JUnit Jupiter (org.junit.jupiter:junit-jupiter:5.10.2) σε πεδίο εφαρμογής test. Έπειτα επαληθεύστε το δέντρο εξαρτήσεων.


Διόρθωση — Αναμενόμενο μπλοκ <dependencies>

xml
<dependencies>

    <!-- Gson : χρησιμοποιείται παντού στον κώδικα (scope compile από προεπιλογή) -->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.10.1</version>
    </dependency>

    <!-- JUnit : μόνο δοκιμές -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.10.2</version>
        <scope>test</scope>
    </dependency>

</dependencies>

Επαλήθευση:

bash
# Λήψη και εμφάνιση του δέντρου εξαρτήσεων
mvn dependency:tree

Αναμενόμενο αποτέλεσμα:

com.exemple:mon-app:jar:1.0.0-SNAPSHOT
+- com.google.code.gson:gson:jar:2.10.1:compile
\- org.junit.jupiter:junit-jupiter:jar:5.10.2:test
   +- org.junit.jupiter:junit-jupiter-api:jar:5.10.2:test
   +- org.junit.jupiter:junit-jupiter-params:jar:5.10.2:test
   \- org.junit.jupiter:junit-jupiter-engine:jar:5.10.2:test

Παρατηρήστε ότι το junit-jupiter φέρνει αυτόματα -api, -params και -engine: αυτές είναι οι μεταβατικές του εξαρτήσεις. Δηλώσατε μία μόνο γραμμή, το Maven έλυσε τα υπόλοιπα.

↑ Επιστροφή στην αρχή


9 — Σύνοψη

Σημεία προς απομνημόνευση

  1. Μια εξάρτηση είναι εξωτερική βιβλιοθήκη, ταυτοποιημένη από τις συντεταγμένες GAV.
  2. Τη δηλώνετε στο <dependencies>· το Maven την κατεβάζει και την αποθηκεύει στην κρυφή μνήμη στο ~/.m2.
  3. Τα πεδία εφαρμογής (compile, test, provided, runtime) ελέγχουν πότε είναι διαθέσιμη η εξάρτηση.
  4. Τα αποθετήρια: τοπικό (~/.m2), Maven Central (δημόσιο), ιδιωτικό (Nexus/Artifactory).
  5. Η μεταβατική επίλυση φέρνει αυτόματα τις εξαρτήσεις των εξαρτήσεων· το mvn dependency:tree επιτρέπει την επιθεώρησή της.

Η συνέχεια

Μάθημα 04 — Κύκλος ζωής και φάσεις: κατανόηση των φάσεων (compile, test, package, install, deploy) που οργανώνουν την κατασκευή.

↑ Επιστροφή στην αρχή


Με την επιφύλαξη παντός δικαιώματος. Οποιαδήποτε αναπαραγωγή, διάδοση, χρήση ή προσαρμογή αυτού του μαθήματος, εν όλω ή εν μέρει, απαγορεύεται αυστηρά χωρίς την προηγούμενη γραπτή άδεια του Dr. Haythem REHOUMA.

Μάθημα δημιουργημένο από τον Dr. Haythem REHOUMA — Ανάπτυξη και ανάπτυξη λύσεων δεδομένων