聚合与继承的关系
聚合是为了方便快速构建项目,继承是为了消除重复配置
共同点是两者的packaging都是pom,聚合模块与继承关系中的父模块除了pom之外都没有实际内容。
聚合关系与继承关系的比较:
在现有实际项目中,往往发现一个pom既是聚合pom又是父pom,这么做主要是为了方便。一般来说,融合使用聚合和继承没有什么问题。例如,可以将account-aggregator和account-parent合并成为一个新的account-parent,如下:
<modelVersion>4.0.0</modelVersion>
<groupId>com.juvenxu.mvnbook.account</groupId>
<artifactId>account-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Account Parent</name>
<modules>
<module>account-email<module>
<module>account-persist</module>
</modules>
<properties>
<springframework.version>2.5.6</springframework.version>
<junit.version>4.7</junit.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${springframework.version}</version>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugins>
</pluginManagement>
</build>
相应的account-email和account-persist的pom配置也要做微小的修改。本来account-parent和他们位于同级目录,因此需要使用值为../account-parent/pom.xml的relativePath元素。现在新的account-parent在上一层目录,这是Maven默认能识别的父模块位置,因此不再需要配置relativePath,如下:
<parent>
<groupId>com.juvenxu.mvnbook.account</groupId>
<artifactId>account-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>account-email</artifactId>
<name>Account Email</name>
约定优于配置
Java成功的重要原因之一就是他能够屏蔽大部分操作系统的差异,XML流行的原因之一是所有语言都接受他。Maven提倡约定优于配置,这是Maven最核心的设计理念之一。
使用约定可以大量减少配置,先看一个简单的Ant配置文件:
<project name="my-project" default="dist" basedir=".">
<description>
simple example build file
</dedication>
<!-- 设置构建的全局属性 -->
<property name="src" location="src/main/java" />
<property name="build" location="target/classes" />
<property name="dist" location="target" />
<target name="init" >
<!-- 创建时间戳 -->
<tstamp/>
<!-- 创建编译使用的构建目录 -->
<mkdir dir="${build}" />
</target>
<target name="compile" depends="init" description="compile the source" >
<!-- 将Java代码从目录${src}编译至${build} -->
<javac srcdir="${src}" destdir="${build}" />
</target>
<target name="dist" depends="compile" description="generate the distribution">
<!-- 创建分发目录 -->
<mkdir dir="${dist}/lib/" />
<!-- 将${build}目录的所有内容打包至MyProject-${DSTAMP}.jar file -->
<jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}" />
</target>
<target name="clean" description="clean up" >
<!-- 删除${bulid}和${dist}目录树 -->
<delete dir="${build}" />
<delete dir="${dist}" />
</target>
</project>
这段代码做的事情就是清除构建目录、创建目录,编译代码、复制依赖至目标目录、最后打包,做同样的使用Maven需要什么配置呢?maven只需要一个最简单的pom,如下:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.juvenxu.mvnbook</groupId>
<artifactId>my-project</artifactId>
<version>1.0</version>
</project>
但是为了获得这样简洁的配置,用户是需要付出一定的代价的,那就是遵循Maven的约定,Maven会假设用户的项目是这样的:
编译输出目录为:target/classes
打包方式为:jar
包输出目录为:target/
当然你也可以自己定义,个性往往意味着牺牲通用性,意味着增加无谓的复杂度,例如:Maven允许你自定义源码目录
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.juvenxu.mvnbook</groupId>
<artifactId>my-project</artifactId>
<version>1.0</version>
<build>
<sourceDirectory>src/java</sourceDirectory>
</build>
</project>
该例中源码目录变成了src/java而不是默认的src/main/java,这就很容易出现问题了。
反应堆
在一个多模块的Maven项目中,反应堆(Reactor)是指所有模块组成的一个构建结构。对于单模块的项目,反应堆就是该模块本身,但对于多模块项目来说,反应堆就包含了各模块之间继承与依赖的关系,从而能够自动计算出合理的模块构建顺序。
首先我们来看下反应堆的构建顺序
以account-aggregator为例:
<modules>
<module>account-email</module>
<module>account-persist</module>
<module>account-parent</module>
</modules>
该例中,account-aggregator没有依赖模块,因此先构建他,接着account-email,他依赖于account-parent模块,必须先构建account-parent,然后在构建account-email,最后到account-persist的时候由于其依赖的模块已经构建,因此直接构建。
裁剪反应堆
一般来说用户会选择构建整个项目或者选择构建单个模块,但是有些时候,用户会想要构建完整的反应堆中的某些模块。换句话说用户需要实时的裁剪反应堆,输入mvn -h可以看到
-am –also - make 同时构建所列模块的依赖模块 mvn clean install -pl account-email -am,account-email依赖于account-parent所以:
account parent
account eamil
-amd –also make dependents 同时构建依赖于所列模块的模块
mvn clean install -pl account-parent -amd,account-email和account-persist都依赖于account-parent所以:
account parent
account email
account persist
-pl –projects 构建指定的模块,模块之间用逗号分隔,例如:mvn clean install -pl account-email,account-persist
account eamil
account persist
-rf –resume-from 从指定的模块回复反应堆
mvn clean install -rf account-email,完整的反应堆构建顺序中,account-email第三,他之后只有account-persist
account email
account persist
在-pl -am或者-pl -amd的基础上还能应用-rf
mvn clean install -pl account-parent -amd -rf account-email
该命令中-pl和-amd参数会裁剪出一个account-parent,account-email,account-persist,在此基础上-rf从account-email构建
account email
account persist
原文地址:http://blog.csdn.net/fuyuwei2015/article/details/46367997