inheritance - 使Maven聚合器pom将属性注入(inject)模块poms中的可行性(不使用继承)

标签 inheritance properties maven aggregate multi-module

关于Maven,您可能会遇到一些问题。特别是关于是否可以在聚合pom中定义属性,然后将其注入到引用的模块中,从而允许该模块在本地覆盖继承层次结构中定义的默认属性。

如果您对具体细节感兴趣,我将介绍我的设置。在此之前,我只想说,我们已经作为一个团队广泛讨论了我们的项目结构,它非常适合我们的需求。我们目前不在寻找其他结构的建议,而是专门研究maven是否可以满足我们的需求。

因此,我们的设置;我将其归结为基本要素。我们有两个源项目A和B。每个项目实际上都是另一个项目的子模块,分别是ParentA和ParentB。从技术上讲,ParentA和ParentB具有许多子模块,但是在此示例中,为简单起见,我将仅明确引用每个子模块。到目前为止,一切都很好。 ParentA引用A作为子模块,而A引用ParentA作为其父模块。 B和ParentB之间的关系相同。

现在来了乐趣。我们希望让ParentA和ParentB都拥有一个超级父pom来继承共享的属性和配置,例如dependencyManagement和插件等。但是我们不希望这个超级父pom负责构建。相反,我们想定义一些构建项目,这些构建项目有选择地构建各种模块。在此示例中,我将介绍BuildAB和BuildB。首先构建A,然后构建B,而第二构建仅构建B。实际上,我们有很多这样的交织模块组和依赖项。最后,只是为了完整说明,我们从B到A有一个依存关系。

让我尝试使用一些ascii艺术来绘制它;)

遗产

A --> ParentA --> parent
B --> ParentB --> parent


子模块关系

BuildAB ==> { (ParentA ==> A) (ParentB ==> B) }
BuildB ==> (ParentB ==> B)


依存关系

B > A


现在,就目前而言,无法使用BuildAB和BuildB文件中的属性来定义依赖项;这些Build文件不是任何继承树的一部分,因此不会有任何属性。但是我们确实希望在运行BuildAB和BuildB时以不同的方式控制依赖项版本。仅仅将依赖项放在超级父项中并不能满足我们的要求。

如果您想知道为什么要考虑这样做,那么一个团队可能正在开发B模块,并且可能还对A进行了较小的修改。其他开发人员可能正在为项目A进行最新和最出色的工作,这要归功于项目B对B的影响。感谢Mercurial,我们在源代码中拥有出色的处理机制。但是我们真的很难与Maven一起使用。

理想情况下,每个Build文件首先要依赖于从Parent继承的子模块。但是,当我们需要重写此继承时,我们希望能够在Build文件中指定可注入属性,这些属性的作用就好像它们最初是在模块中指定的一样。当然,所有这些都无需实际修改受源代码控制的pom。

我们想评估的是,是否存在通过插件或补丁来修改Maven的范围。

我们以前从未写过插件(坦率地说,有关此的教程和在线内容很少,并且对开发人员不十分友好-除非有人错过了我的优秀教程:)),但如果您愿意,可以尝试一下似乎可行。

所以基本上


您之前是否曾处理过类似的要求并使其与现有插件一起使用?
我们缺少一个简单的技巧吗?
您是否编写了类似的插件并且可以推荐一个起点?
您是否知道任何实际原因导致此类插件无法正常工作?
您是否在研究Maven源代码,并且知道我们是否能够提供任何结果代码...以及我们从哪里开始寻找我们愿意的代码。


最后的评论。我们使用Eclipse进行开发,因此我们也需要构建而无需注入属性。我希望这将通过正常的继承树进行。

非常感谢,我知道这是一个棘手的问题。

最佳答案

对于各种特殊魔术:使用Maven构建扩展。

这是一个鲜为人知的机制(通常对于Maven来说,是一个叹息),没有得到充分记录的机制,但是据我所知,它确实是一种正式认可的影响整个构建过程的方式。

import org.apache.maven.AbstractMavenLifecycleParticipant;
import org.apache.maven.execution.MavenSession;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;

@Component(role = AbstractMavenLifecycleParticipant.class, hint = "mySpecialService")
public class MySpecialExtension
    extends AbstractMavenLifecycleParticipant
{

    @Requirement
    private Logger logger;

    @Override
    public void afterProjectsRead( MavenSession session ) {
        // ...do you magic here

        // for example, to set some POM properties
        Properties sysProps = session.getSystemProperties();
        ....
        Properties projProps = session.getCurrentProject().getProperties();
        projProps.setProperty("..",val);


在解析pom.xml文件并在内存中构建基本POM之后,但是在任何进一步的构建活动开始之前,将立即调用此函数。在多模块项目中,即使仅在某些子模块中定义了扩展,也会从根项目中调用该扩展。在这一点上,理论上您可以对构建过程进行任何操作,例如仅将一些属性注入pom,从人工制品管理器中加载其他项目并将其添加到构建反应器中,查找一些特定的插件,重塑POM的POM。一些模块甚至构建未在任何地方声明的东西(!)

要构建这样的扩展,请将代码放入单独的Maven项目中

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <prerequisites>
        <maven>3.0</maven>
    </prerequisites>

    <name>my-special-service</name>
    <groupId>my.group</groupId>
    <artifactId>my-special-service</artifactId>
    <packaging>jar</packaging>

    <parent>
       ....
    </parent>

    <properties>
        <mavenApiVer>3.0.5</mavenApiVer>
        <mavenModelVer>2.2.1</mavenModelVer>
    </properties>

<build>
    <plugins>
        <!-- Maven Build Extension -->
        <plugin>
            <groupId>org.codehaus.plexus</groupId>
            <artifactId>plexus-component-metadata</artifactId>
            <version>1.5.5</version>
            <executions>
                <execution>
                    <goals>
                        <goal>generate-metadata</goal>
                        <!-- goal>generate-test-metadata</goal -->
                    </goals>
                </execution>
            </executions>
            </plugin>
            <!-- Maven Build Extension -->
        </plugins>
    </build>


    <dependencies>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-project</artifactId>
            <version>${mavenModelVer}</version>
        </dependency>

        <!-- Maven Build Extension -->
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-compat</artifactId>
            <version>${mavenApiVer}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-core</artifactId>
            <version>${mavenApiVer}</version>
        </dependency>
        <!-- Maven Build Extension -->

        ....

    </dependencies>
</project>


为了在其他项目中使用您的扩展程序,只需添加以下内容

<build>
    <extensions>
        <extension><!-- Maven Build Extension: my Special Service -->
            <groupId>my.group</groupId>
            <artifactId>my-special-service</artifactId>
            <version>.....</version>
        </extension>
    </extensions>

    <pluginManagement>
    ....




在我们的特定用例中,我们提供了一些常规服务(尤其是数据库URL
(需要在构建过程中从特定的插件中使用),我们需要透明地从配置管理系统中检索。向环境中的每个开发人员和每个构建服务器分发属性文件是不切实际的
异构的方式。

关于inheritance - 使Maven聚合器pom将属性注入(inject)模块poms中的可行性(不使用继承),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5489311/

相关文章:

java - aws.accessKeyId 和 aws.secretKey 未被读取

java - 如何使用 pom.xml 更新属性文件中的环境值

tomcat - 构建一个可以通过Maven Tomcat插件部署的war文件

java - 让 Maven 复制构建 jar 中的其他文件(不是资源,而是任何包中的任何文件)?

java - 继承,每一步之后发生了什么

inheritance - Go 中创建复杂结构层次结构的惯用方法是什么?

Java 8 - 使用双冒号语法调用接口(interface)的默认方法

JavaScript 继承 Object.create

java - 如何配置Spring从jar外部加载application.properties?

java - 仅从 Maven 测试调用 init 方法失败 ested 异常为 java.lang.UnsupportedOperationException