问题描述
我有一个项目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中包含的接口中使用第四个项目C中包含的实现,该项目以与项目A相同的版本来实现I,只需更改构建它的命令行即可。
我知道可以使用配置文件属性来实现,但是在项目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时的依赖关系。
1楼
因此A
对I
罚款;
A
对I
有依赖性。
可以将C
的I
实现作为jar添加到A
,方法之一是:
-
<scope>runtime<scope>
或 -
<scope>provided<scope>
如果jar其中A
运行时,有一个罐子C
。
然后是没有依赖性的问题。
如果jar C
使用Java SPI (服务提供商接口),则可以让A
在某些接口上进行查找:
一世
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
2楼
也许您没有采取正确的方法。 在我看来,这听起来像是尝试将程序静态链接到一个或另一个库上-Java无法那样工作。
Java全部涉及动态链接。 没有什么可以阻止您在不完全引用B或C的情况下将A和I一起编译的-它只是编译,但是由于在I中没有接口的实现,因此它将在执行期间的某个时间抛出异常。
您应该只实现某种抽象工厂,在寻找适当的实现之后返回I对象。 该工厂决策的标准可以从某些属性文件中获取,或深入研究反射/带注释的类等。
分发应用程序时,只需将A和I jar打包在一起以实现:B,C或将来要扩展应用的任何对象(D,E等)。在运行时,您的AbstractFactory将具有根据应用程序设置和可用的实施方案做出决定。
例如,考虑一下Windows Media Player(我知道,技术不同,但思路相同),以及它如何寻找编解码器实现,以及一旦我们下载并注册了它们,就可以直接播放剪辑而无需对软件本身进行任何修改。