我什么时候需要与运行时范围的maven依赖

时间:2017-08-23 14:36:28

标签: java maven jar dependencies

我正在尝试了解maven中runtime作用域依赖的特定需求。在哪种情况下,我需要这样做,compileprovided范围都不会?

例如,当我必须在代码中直接调用库API(针对它进行编译)并将依赖项打包到工件或依赖项目工件中时,我会使用compile作用域作为依赖项。

当我必须针对API进行编译时,我会使用provided范围,但不要打包它(除了它在运行时可用)。

但我什么时候需要runtime范围?这是针对什么情况,当我不直接调用库API(而是使用反射),但是想要将它打包到工件中?为什么不只是使用compile范围?唯一的好处是编译时间更快,或runtime范围内有哪些其他特殊功能无法通过compile范围实现或避免?

4 个答案:

答案 0 :(得分:14)

runtime范围的所有功能也可以使用默认范围完成:compile
那么为什么要使用runtime

因为在某些情况下,这非常有意义,可以让您的构建更加健壮

一个典型的用例是确保客户端代码不使用特定的实现。

假设您构建了一个依赖于打包为Maven依赖项(my-service-api)的API的应用程序,并且此API的实现被打包为另一个Maven依赖项(my-service-impl)。 假设您现在需要在构建的应用程序的运行时提供实现,但您不希望您的应用程序的客户端代码直接引用实现。

使用runtime的{​​{1}}范围:

my-service-impl

由于编译器永远不会在类路径中具有依赖关系,因此无法在应用程序的客户端代码中创建与实现的任何耦合。
客户端代码只会看到依赖项的API:

使用<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> 的{​​{1}}范围:

compile

情况有所不同:您可能会错误地引用实现类,因此会与实现产生不合需要的耦合。

支持my-service-impl范围的已知用法是因为您必须处理特定DBMS(Oracle,PostgreSQL或其他)的JDBC依赖关系。
要编写可移植代码,您不希望允许客户端代码引用此JDBC依赖项的类,但您希望所有相同的内容都包含在应用程序中,因为在运行时需要使用类来使JDBC api与这个DBMS。

答案 1 :(得分:3)

围绕runtime范围存在相当大的混淆。我认为这种混淆反映了它的边际效益以及缺乏真正引人注目的通用用例。

常见的好处是:

  • 它们有助于避免意外依赖
  • 它们有助于Class.forName("a.b.ClassName")之类的用法,并允许您切换由&#34; a.b.ClassName&#34;表示的绑定。无需重新编译您的应用程序。此优点的常见示例:JDBC驱动程序和SLF4J绑定

但是,考虑到一般的困惑和边际收益,我建议坚持compile范围,除非您遇到runtime范围非常有用的其中一个极端情况。

答案 2 :(得分:1)

运行时范围的依赖项对于动态加载的库非常有用,您不需要在代码中显式引用,但需要在那里运行应用程序。

答案 3 :(得分:1)

  

运行时   此范围表示编译不需要依赖项,但是用于执行。它位于运行时和测试类路径中,但不是编译类路径。

这意味着库中的类存在于JVM类路径(运行时环境)中,但不存在于JAVA编译器类路径(编译时),因此在编译项目时,编译器将无法看到这些类..因此,您无法在编译时使用/导入任何这些类。 此范围对于动态加载的类(即,将在运行时引用/加载的类)非常有用