Çalışma zamanı ve derleme zamanı arasındaki farkı ve ikisi arasında nasıl ayrım yapılacağını anlıyorum, ancak derleme zamanı ve çalışma zamanı bağımlılıkları arasında bir ayrım yapma gereğini görmüyorum.
Genel derleme zamanı ve çalışma zamanı kavramları ve Maven'e özgü compile
ve runtime
kapsam bağımlılıkları iki çok farklı şeydir. Bunlar aynı çerçeveye sahip olmadığından bunları doğrudan karşılaştıramazsınız: genel derleme ve çalışma zamanı kavramları genişken, maven compile
ve runtime
kapsam kavramları özellikle zamana göre bağımlılıklar kullanılabilirliği / görünürlüğü ile ilgilidir: derleme veya yürütme.
Maven'in her şeyden önce bir javac
/ java
sarmalayıcı olduğunu ve Java'da belirttiğiniz bir derleme zamanı sınıf yoluna javac -cp ...
ve belirlediğiniz bir çalışma zamanı sınıf yoluna sahip olduğunuzu unutmayın java -cp ...
.
Maven compile
kapsamını hem Java derlemesinde hem de çalışma zamanı sınıfında bir bağımlılık eklemenin bir yolu olarak düşünmek yanlış olmaz (javac
ve java
) Maven runtime
kapsamı yalnızca Java çalışma zamanı classppath ( javac
) içinde bir bağımlılık eklemenin bir yolu olarak görülebilir .
Boğulduğum şey şudur: Bir program, derleme sırasında bağlı olduğu çalışma zamanında bir şeye nasıl bağlı kalmaz?
Tanımladığınız şeyin kapsamı runtime
ve ilişkisi yoktur compile
. Bir bağımlılığın, çalışma zamanında değil, derleme zamanında buna bağlı olması için belirttiğiniz kapsama
daha çok benziyor provided
.
Derlemek için bağımlılığa ihtiyaç duyduğunuzda kullanırsınız, ancak bunu paketlenmiş bileşene (JAR, WAR veya diğerleri) dahil etmek istemezsiniz çünkü bağımlılık zaten ortam tarafından sağlanır : sunucuya dahil edilebilir veya herhangi bir Java uygulaması başlatılırken belirtilen sınıf yolunun yolu.
Java uygulamam log4j kullanıyorsa, o zaman derlemek için (kodum log4j içinden üye yöntemleriyle bütünleşen ve bunları çağıran kodum) ve çalışma zamanının (kodumun log4j içinde kod olduğunda ne olacağı üzerinde kesinlikle hiçbir kontrolü yoktur) için log4j.jar dosyasına ihtiyaç duyar .jar çalıştırılır).
Bu durumda evet. Ancak daha sonra başka bir günlük uygulamasına (log4J 2, logback veya başka bir) geçebilmek için log4j'nin önünde ön cephe olarak slf4j'ye dayanan taşınabilir bir kod yazmanız gerektiğini varsayalım.
Bu durumda, compile
bağımlılık olarak slf4j belirtmeniz gerekir (bu varsayılandır), ancak bağımlılık olarak log4j bağımlılığını belirteceksiniz runtime
:
<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>
Bu şekilde, log4j sınıflarına derlenen kodda başvurulamaz, ancak yine de slf4j sınıflarına başvurabilirsiniz.
İki bağımlılığı compile
zamanla belirttiyseniz, hiçbir şey derlenen kodda log4j sınıflarına başvurmanızı engellemez ve böylece günlük uygulamasıyla istenmeyen bir bağlantı oluşturabilirsiniz:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>...</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>...</version>
</dependency>
runtime
Kapsamın yaygın bir kullanımı , JDBC bağımlılık bildirimidir. Taşınabilir kod yazmak için, istemci kodunun belirli DBMS bağımlılık sınıflarına başvurmasını istemezsiniz (örneğin: PostgreSQL JDBC bağımlılığı), ancak sınıfların yapması gereken çalışma zamanında uygulamanıza dahil edilmesini istersiniz. JDBC API bu DBMS ile çalışır.