如何切换maven项目?

时间:2013-05-24 09:25:38

标签: java maven

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

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

public class Customer(){
    private String name;

    public String getName(){
        return name;
    }

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

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

P.S。如果问题不明确,请问我。

2 个答案:

答案 0 :(得分: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>

答案 1 :(得分:1)

我找到的解决方案非常类似于Macias的帖子,但是来自真实的代码。

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

让我们以slf4j项目为例,您可以从http://www.slf4j.org/download.html

下载资源

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

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

这是“inteface”API。

对于“实现”API slf4j-api 项目包含带有3个存根类的impl包: StaticLoggerBinder StaticMarkerBinder StaticMDCBinder < / em> LoggerFactory 类中使用哪些方法,但在 slf4j-api 项目中,它们会抛出UnsupportedException。

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

现在让我们来看看Maven魔术出现的地方。回想一下,“inteface”和“implementation”项目都有相同的类 StaticLoggerBinder StaticMarkerBinder StaticMDCBinder 。查看 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 继续构建并将实际的“实现”类放入“而不是”存根。