When would I need maven dependency with runtime sc

2019-06-17 10:32发布

问题:

I'm trying to understand the specific need for runtime scoped dependency in maven. In which situation I would need this, where neither compile or provided scope won't do?

For example, I would use compile scope for dependency, when I have to call the library API directly in the code (compile against it) and package the dependency in the artifact or dependent project artifacts.

I would use provided scope when I have to compile against the API, but don't package it (rather except it to be available at runtime).

But when would I need runtime scope? Is this for situations, when I don't directly call the library API (rather use reflection), but want to package it inside the artifact? Why not just to use compile scope? Is the only benefit faster compile time, or is there something other special in runtime scope that couldn't be achieved or avoided with compile scope?

回答1:

All what you can do with the runtime scope can be also done with the default scope : compile.
So why use runtime?

Because in some cases, this makes really sense and can make your build more robust.

A typical use case is ensuring that the client code doesn't use a specific implementation.

Suppose you build an application relying on an API packaged as a Maven dependency (my-service-api) and the implementation of this API is packaged as another Maven dependency (my-service-impl).
Suppose now you need to provide the implementation at the runtime in the built application but you don't want that the client code of your application refers directly the implementation.

By using the runtime scope for my-service-impl:

<dependencies>
​  <dependency>
​      <groupId>my-group</groupId>
​      <artifactId>my-service-api</artifactId>
​  </dependency>
​  
​  <dependency>
​      <groupId>my-group</groupId>
​      <artifactId>my-service-impl</artifactId>
​      <scope>runtime</scope>
​  </dependency>
<dependencies>

As the compiler will never have the dependency in the classpath, you cannot create any coupling with the implementation in the client code of your application.
Client code will only see the API of the dependency :

By using the compile scope for my-service-impl:

<dependencies>
​  <dependency>
​      <groupId>my-group</groupId>
​      <artifactId>my-service-api</artifactId>
​  </dependency>
​  
​  <dependency>
​      <groupId>my-group</groupId>
​      <artifactId>my-service-impl</artifactId>    ​  
​  </dependency>
<dependencies>

Things are different : you could by mistake reference implementation classes and so create an undesirable coupling with the implementation.

A known usage to favor runtime scope is as you have to cope with a JDBC dependency of a specific DBMS (Oracle, PostgreSQL or whatever).
To write portable code, you don't want to allow the client code to refer to classes of this JDBC dependency but you want all the same include it in your application as at runtime the classes are needed to make the JDBC api works with this DBMS.



回答2:

There is considerable confusion around the runtime scope. I think this confusion reflects its marginal benefit and the absence of a really compelling general purpose use case for it.

The commonly cited benefits are:

  • They help avoid accidental dependencies
  • They facilitate usages such as Class.forName("a.b.ClassName") and allow you to switch the binding represented by "a.b.ClassName" without having to recompile your application. Common examples of this benefit: JDBC drivers and SLF4J bindings

But, given the general confusion and the marginal benefits I'd suggest sticking to compile scope unless you have encountered one of those corner cases where runtime scope is really useful.



回答3:

Runtime scoped dependencies are useful for dynamically loaded libraries, that you do not explicitly reference in the code but need to be there for your application to run.



回答4:

runtime This scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath.

Well it means that the classes within the library are present to the JVM classpath (runtime environment), but not to the JAVA Compiler classpath (compile-time), therefore when compiling your project these classes will not be visible to the compiler.. therefore you cannot use/import any of these classes at compile-time. This scope is useful for dynamically-loaded classes (that is, classes that you will reference/load at runtime)