关于Maven的一些可行性问题。特别是,我们是否可以在聚合pom中定义属性然后将它们注入到引用的模块中,从而允许该模块在本地覆盖继承层次结构中定义的默认属性。
如果您对细节感兴趣,我会描述我的设置。在此之前,我要说的是,我们已经广泛讨论了我们的项目结构,并且非常符合我们的需求。我们目前不是在寻找其他结构的建议,而是专门探讨maven是否能满足我们的需求。
所以,我们的设置;我会把它归结为必需品。我们有两个源项目,A和B.这些项目实际上分别是另一个的子模块,ParentA和ParentB。 ParentA和ParentB在技术上有许多子模块,但在这个例子中,为了简单起见,我只会明确引用一个子模块。到现在为止还挺好。 ParentA引用A作为子模块,A引用ParentA作为其父模块。 B和ParentB之间也存在相同的关系。
现在很有趣。我们希望ParentA和ParentB的超级父pom继承共享属性和配置,例如dependencyManagement和plugins等。但是我们不希望这个超级父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文件中的属性来定义依赖项;这些构建文件不是任何继承树的一部分,因此没有任何内容可以获取属性。但是我们想要在运行BuildAB和BuildB时以不同方式控制依赖版本。简单地将依赖项放在超级父级中并不会为了我们的要求而削减它。
如果您想知道为什么可能会考虑一个团队可能正在开发B模块,并可能对A进行微小修改。其他开发人员可能正致力于最新和最好的项目A,由于依赖性,它对B产生了影响。由于Mercurial,我们有很好的机制来处理源代码。但我们真的很难与Maven合作。
理想情况下,每个Build文件在第一个实例中都依赖于从Parent继承的子模块。但是当我们需要覆盖这个继承时,我们希望能够在Build文件中指定可注入的属性,它们的行为就像最初在模块中指定的那样。当然,所有这些都没有实际修改受源控制的pom。
我们想要评估的是,是否有任何范围可以通过插件或补丁修改maven来执行此操作。
我们之前从未写过插件(坦率地说,关于这个的教程和内容很少,而且不是真正的开发人员友好 - 除非有人有一个我错过的好教程:))但我们愿意给它如果看起来可行的尝试。
所以,基本上,
最后一条评论。我们在Eclipse中开发,因此我们还需要构建才能在不注入属性的情况下工作。我希望这可以通过普通的继承树。
非常感谢所有人,我知道这是一个棘手的问题。
答案 0 :(得分:2)
对于各种特殊魔术:使用 maven build extension 。
这是一个众所周知的(并且像往常一样对于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中,从artefact管理器加载更多项目并将它们添加到构建反应器,查找一些特定的插件,重塑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) 我们需要从配置管理系统中透明地检索构建过程中的特定插件。将属性文件分发给每个开发人员和每个构建服务器都不实用,因为环境是 异化的方式。