我有一个项目A,该项目取决于一个包含由第三个项目B实现的接口的项目I。
我希望在编译时将项目B动态插入项目A的pom.xml中,而不更改A的pom.xml并通过命令行向Maven提供属性(示例
mvn package -Dmodule.artifactId=[B_ARTIFACTID] -Dmodule.version=[B_VERSION]
),其中B_ARTIFACTID
和B_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时它不会解决依赖性。
答案 0 :(得分:1)
因此A
对I
的编译很好; A
与I
之间存在依赖性。
I
中C
的实现可以通过以下任一方式作为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(我知道,技术不同,但思路相同),以及它如何寻找编解码器实现,以及一旦我们下载并注册了它们,就可以直接播放剪辑而无需对软件进行任何修改本身。