Entiendo la diferencia entre tiempo de ejecución y tiempo de compilación y cómo diferenciar entre los dos, pero no veo la necesidad de hacer una distinción entre dependencias de tiempo de compilación y tiempo de ejecución.
Los conceptos generales de tiempo de compilación y tiempo de ejecución y las dependencias específicas compile
y de runtime
alcance de Maven son dos cosas muy diferentes. No puede compararlos directamente ya que estos no tienen el mismo marco: los conceptos generales de compilación y tiempo de ejecución son amplios, mientras que los conceptos de maven compile
y runtime
alcance tratan específicamente sobre la disponibilidad / visibilidad de las dependencias según el tiempo: compilación o ejecución.
No olvides que Maven es sobre todo un javac
/ java
wrapper y que en Java tienes una ruta de clase de tiempo de compilación que especificas javac -cp ...
y una ruta de clase de tiempo de ejecución que especificas java -cp ...
.
No sería incorrecto considerar el compile
alcance de Maven como una forma de agregar una dependencia tanto en la compilación de Java como en la classppath en tiempo de ejecución (javac
y java
) mientras que el runtime
alcance de Maven puede verse como una forma de agregar una dependencia solo en el tiempo de ejecución de Java classppath ( javac
).
Con lo que me estoy asfixiando es esto: ¿cómo puede un programa no depender de algo en tiempo de ejecución de lo que dependía durante la compilación?
Lo que usted describe no tiene ninguna relación runtime
ni compile
alcance.
Se parece más al provided
alcance que especifica para que una dependencia dependa de eso en el tiempo de compilación pero no en el tiempo de ejecución.
Lo usa porque necesita la dependencia para compilar, pero no desea incluirlo en el componente empaquetado (JAR, WAR o cualquier otro) porque la dependencia ya la proporciona el entorno: se puede incluir en el servidor o en cualquier Se inicia la ruta de la ruta de clases especificada cuando se inicia la aplicación Java.
Si mi aplicación Java usa log4j, entonces necesita el archivo log4j.jar para compilar (mi código se integra e invoca métodos de miembros desde dentro de log4j) así como el tiempo de ejecución (mi código no tiene absolutamente ningún control sobre lo que sucede una vez que el código dentro de log4j .jar se ejecuta).
En este caso sí. Pero suponga que necesita escribir un código portátil que se base en slf4j como fachada frente a log4j para poder cambiar a otra implementación de registro más adelante (log4J 2, logback o cualquier otro).
En este caso, en su pom, debe especificar slf4j como una compile
dependencia (es el valor predeterminado) pero especificará la dependencia log4j como una runtime
dependencia:
<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>
De esta manera, las clases log4j no podrían ser referenciadas en el código compilado pero aún podrá referirse a clases slf4j.
Si especificó las dos dependencias con el compile
tiempo, nada le impedirá hacer referencia a las clases log4j en el código compilado y podría crear un acoplamiento no deseado con la implementación de registro:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>...</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>...</version>
</dependency>
Un uso común del runtime
alcance es la declaración de dependencia de JDBC. Para escribir código portátil, no desea que el código del cliente pueda referirse a clases de la dependencia DBMS específica (por ejemplo: dependencia PostgreSQL JDBC) pero desea que de todos modos lo incluya en su aplicación, ya que en tiempo de ejecución las clases son necesarias para hacer la API de JDBC funciona con este DBMS.