0

让我从例子开始。假设有工厂接口和客户类:

public interface CustomerFactory(){
    Customer create();
}

public class Customer(){
    private String name;

    public String getName(){
        return name;
    }

    public void setName(String name){
        this.name = name;
    }
}

假设我有需要CustomerFactory的CustmerProject maven 项目。我想用CustomerFactory实现创建几个 maven 项目(每个项目一个实现),但我不希望CustmerProject依赖于所有这些实现项目。我想创建一个CustmerProject将依赖的 CustomerFactoryIntefaceProject,并将CustomerFactoryImplementationProject之一作为CustomerFactoryIntefaceProject。我知道这是可能的,但我如何在实践中做到这一点?

PS如果问题不清楚,问我。

4

2 回答 2

1

您可以参数化 ArtifactId 或 CustomerFactoryImplementationProject 的版本,并使用 Maven 配置文件在构建期间选择实现。

假设您有以下工件:

  • 顾客
  • 客户工厂 1
  • 客户工厂 2

因此,在客户项目的 pom.xml 中,您将需要:

<dependency>
    <groupId>base</groupId>
    <artifactId>${customer.factory.artifact}</artifact>
    <version>123</version>
</dependency>
....
<profiles>
    <profile>
        <id>customerFactory1</id>
        <properties>
            <customer.factory.artifact>customer-factory-1</customer.factory.artifact>
        </properties>
     </profile>
     <profile>
        <id>customerFactory2</id>
        <properties>
            <customer.factory.artifact>customer-factory-2</customer.factory.artifact>
        </properties>
     </profile>
</profiles>

现在只需在构建过程中选择配置文件,如下所示:

mvn -P customerFactory2 install

...或者实际上您可以直接分析依赖块:

<profiles>
    <profile>
        <id>customerFactory1</id>
        <dependencies>
             <dependency>
                 <groupId>base</groupId>
                 <artifactId>customer-factory-1</artifact>
                 <version>123</version>
             </dependency>
        </dependencies>
     </profile>
     <profile>
        <id>customerFactory2</id>
        <dependencies>
             <dependency>
                 <groupId>base</groupId>
                 <artifactId>customer-factory-2</artifact>
                 <version>123</version>
             </dependency>
        </dependencies>
     </profile>
</profiles>
于 2013-05-24T09:32:28.913 回答
1

我找到了与 Macias 的帖子非常相似的解决方案,但来自真实代码。

主要思想是将存根类放入“接口”项目中,添加将在流程类阶段删除存根类的插件,使“实现”项目依赖于“接口”并使用具有相同包和类的真实代码创建类命名为存根。

我们以 slf4j 项目为例,您可以从http://www.slf4j.org/download.html下载源代码

主要项目是slf4j-api,包含接口:LoggerLocationAwareLogger(扩展Logger)、ILoggerFactory等,还包含LoggerFactory类(和几个 Utility 类),在创建 logger 时使用,例如:

private static final Logger logger = LoggerFactory.getLogger(SomeClass.class);

这是“接口”API。

对于“实现”API ,slf4j-api项目包含具有 3 个存根类的 impl 包:StaticLoggerBinderStaticMarkerBinderStaticMDCBinder,这些方法在LoggerFactory类中使​​用,但在slf4j-api项目中它们抛出 UnsupportedException。

现在让我们看一下slf4j-jdk14项目,它依赖于slf4j-api并且只包含 impl 包和前面提到的 3 个类:StaticLoggerBinderStaticMarkerBinderStaticMDCBinder;和JDK14LoggerAdapterJDK14LoggerFactoryslf4j-api实现LocationAwareLoggerILoggerFactory。但它们不是存根,它们有一个真实的代码,例如StaticLoggerBinder返回产生JDK14LoggerAdapter的JDK14LoggerFactory

现在让我们看看 Maven 魔法发挥作用的地方。回想一下,“接口”和“实现”项目都具有相同的类StaticLoggerBinderStaticMarkerBinderStaticMDCBinder。查看slf4j-api pom.xml并找到构建标签:

<project>
    ...
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    ...
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <executions>
                <execution>
                    <phase>process-classes</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
                </executions>
                <configuration>
                <tasks>
                    <echo>Removing slf4j-api's dummy StaticLoggerBinder and StaticMarkerBinder</echo>
                    <delete dir="target/classes/org/slf4j/impl"/>
                </tasks>
                </configuration>
            </plugin>
        </plugins>
    </build>
    ...
</project>

因为slf4j-jdk14依赖于slf4j-api所以首先构建 slf4j-api,然后插件删除存根,然后继续构建slf4j-jdk14并放置实际的“实现”类“而不是”存根。

于 2013-05-24T17:13:37.923 回答