Saya memahami perbedaan antara waktu proses dan waktu kompilasi serta cara membedakan keduanya, tetapi saya tidak melihat kebutuhan untuk membuat perbedaan antara dependensi waktu kompilasi dan waktu proses.
Konsep umum waktu kompilasi dan runtime serta dependensi spesifik compile
dan runtime
cakupan Maven adalah dua hal yang sangat berbeda. Anda tidak dapat membandingkannya secara langsung karena keduanya tidak memiliki bingkai yang sama: konsep umum kompilasi dan runtime luas sedangkan konsep maven compile
dan runtime
cakupan secara khusus membahas ketersediaan / visibilitas dependensi sesuai dengan waktu: kompilasi atau eksekusi.
Jangan lupa bahwa Maven di atas segalanya adalah a javac
/ java
wrapper dan bahwa di Java Anda memiliki classpath waktu kompilasi yang Anda tentukan javac -cp ...
dan classpath waktu proses yang Anda tentukan java -cp ...
.
Tidak salah jika mempertimbangkan compile
cakupan Maven sebagai cara untuk menambahkan dependensi baik dalam compile Java maupun classppath waktu proses (javac
dan java
) sementara runtime
cakupan Maven bisa dilihat sebagai cara untuk menambahkan dependensi hanya di classppath ( javac
) runtime Java .
Apa yang saya tersedak adalah ini: bagaimana sebuah program tidak bergantung pada sesuatu pada saat runtime yang bergantung padanya selama kompilasi?
Apa yang Anda gambarkan tidak memiliki hubungan runtime
dan compile
ruang lingkup.
Sepertinya lebih banyak provided
cakupan yang Anda tentukan agar dependensi bergantung padanya pada waktu kompilasi tetapi tidak pada waktu proses.
Anda menggunakannya karena Anda memerlukan dependensi untuk dikompilasi tetapi Anda tidak ingin memasukkannya ke dalam komponen yang dikemas (JAR, WAR, atau lainnya) karena dependensi tersebut sudah disediakan oleh lingkungan: dapat disertakan di server atau yang lainnya. jalur classpath yang ditentukan saat aplikasi Java dimulai.
Jika aplikasi Java saya menggunakan log4j, maka ia membutuhkan file log4j.jar untuk mengkompilasi (kode saya terintegrasi dengan dan memanggil metode anggota dari dalam log4j) serta runtime (kode saya sama sekali tidak memiliki kendali atas apa yang terjadi setelah kode di dalam log4j .jar dijalankan).
Dalam hal ini ya. Tetapi anggaplah Anda perlu menulis kode portabel yang mengandalkan slf4j sebagai fasad di depan log4j untuk dapat beralih ke implementasi logging lain nanti (log4J 2, logback, atau lainnya).
Dalam kasus ini di you pom Anda perlu menentukan slf4j sebagai compile
dependensi (ini adalah default) tetapi Anda akan menentukan dependensi log4j sebagai runtime
dependensi:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>...</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>...</version>
<scope>runtime</scope>
</dependency>
Dengan cara ini, kelas log4j tidak dapat dirujuk dalam kode yang dikompilasi tetapi Anda masih dapat merujuk kelas slf4j.
Jika Anda menentukan dua dependensi dengan compile
waktu, tidak ada yang akan menghalangi Anda untuk mereferensikan kelas log4j dalam kode yang dikompilasi dan Anda dapat membuat penggabungan yang tidak diinginkan dengan implementasi logging:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>...</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>...</version>
</dependency>
Penggunaan umum runtime
ruang lingkup adalah deklarasi ketergantungan JDBC. Untuk menulis kode portabel, Anda tidak ingin kode klien dapat merujuk kelas dependensi DBMS tertentu (misalnya: ketergantungan JDBC PostgreSQL) tetapi Anda ingin semua hal yang sama memasukkannya ke dalam aplikasi Anda karena pada waktu proses kelas perlu membuatnya API JDBC bekerja dengan DBMS ini.