关于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.
我们以前从来没有写过插件(坦率地说,关于这个的教程和内容很少,而且不是真正的开发人员友好 – 除非有人有一个我错过的好教程:))但我们愿意尝试一下这似乎是可行的.
基本上,
>您之前是否已经处理过类似的要求并使用现有的插件?
>我们缺少一个简单的伎俩吗?
>你有没有写过类似的插件,可以推荐一个地方开始?
>您知道为什么这样的插件可能不起作用的任何实际原因?
>您是否正在使用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中,从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)
我们需要从配置管理系统中透明地检索构建过程中的特定插件.将属性文件分发给每个开发人员和每个构建服务器都不实用,因为环境是
异化的方式.