在编译时在pom.xml中动态添加依赖项,而无需了解工件ID和版本

时间:2019-02-22 08:41:02

标签: java eclipse maven

我有一个项目A,该项目取决于一个包含由第三个项目B实现的接口的项目I。

我希望在编译时将项目B动态插入项目A的pom.xml中,而不更改A的​​pom.xml并通过命令行向Maven提供属性(示例

mvn package -Dmodule.artifactId=[B_ARTIFACTID] -Dmodule.version=[B_VERSION]

),其中B_ARTIFACTIDB_VERSION指的是项目B。

目标是标记项目A的版本,并通过I中包含的接口使用包含在与项目A相同版本中实现I的第四个项目C中包含的实现,只需更改构建它的命令行即可

我知道可以使用概要文件属性来实现,但是在标记项目A时,它不会解决依赖关系,如何在不使用默认依赖关系的情况下解决此问题?

B和C取决于由以下项目标识的项目:

<groupId>project</groupId>
<artifactId>I</artifactId>
<version>0.1.0.0</version>

项目A

<dependencies>
  <dependency>
    <groupId>project</groupId>
    <artifactId>I</artifactId>
    <version>0.1.0.0</version>
    <dependency>
      <dependency>
        <groupId>project</groupId>
        <artifactId>???</artifactId>
        <version>???</version>
        <scope>runtime</scope>
        <dependency>

编辑:我说我不想使用属性,因为在我标记项目A时它不会解决依赖性。

2 个答案:

答案 0 :(得分:1)

因此AI的编译很好; AI之间存在依赖性。

IC的实现可以通过以下任一方式作为jar添加到A中:

  • <scope>runtime<scope>
  • <scope>provided<scope>,如果运行jar A的地方有一个jar C

然后是没有依赖性的问题。

如果jar C使用 java SPI (服务提供商接口),则可以让A在某些接口上进行查找:

  • I

    package net.i.api; interface Api { ... }
    
  • C

    package net.c.api; class ApiImpl implements Api { ... }
    
    • 文本文件/META-INF/services/net.i.api.Api

      net.c.api.ApiImpl
      

答案 1 :(得分:1)

也许您没有采用正确的方法。在我看来,这听起来像是尝试将程序静态链接到一个或另一个库上-Java无法那样工作。

Java全部涉及动态链接。没有什么可以阻止您在不完全引用B或C的情况下将A和I一起编译的-它只是编译,但是由于在I中没有接口的实现,因此它将在执行期间的某个时间抛出异常。

您应该只实现某种抽象工厂,在寻找适当的实现之后返回I对象。该工厂决策的标准可以从某些属性文件中获取,也可以深入研究反射/带注释的类等。

https://en.wikipedia.org/wiki/Abstract_factory_pattern

Scanning Java annotations at runtime

分发应用程序时,只需将A和I jar打包在一起即可实现:B,C或将来要扩展应用程序的任何内容(D,E等)。在运行时,您的AbstractFactory将必须根据应用程序设置和可用的实现来做出决定。

以一个示例为例,考虑一下Windows Media Player(我知道,技术不同,但思路相同),以及它如何寻找编解码器实现,以及一旦我们下载并注册了它们,就可以直接播放剪辑而无需对软件进行任何修改本身。