概述
聚合的动机是为了方便一起编译;继承的作用是为了统一依赖管理;搞清楚这两个方面就很容易使用他们了。依赖范围为 import 则是为了解决单继承问题。
聚合
例如我有一个 provider项目,该项目中又包含了 provider-bit 和 provider-api 两个子项目,provider 即使用了聚合,又使用了继承。我们来看一下 provider 根目录下的 pom.xml 文件
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.bbm</groupId> <artifactId>demo</artifactId> <version>1.0.0</version> <name>demo</name> <description>Demo project for Spring Boot</description> <!-- 父pom聚合了两个子项目,那么编译的时候就会一起编译 --> <modules> <module>provider-api</module> <module>provider-bit</module> </modules> <packaging>pom</packaging> <properties> <java.version>1.8</java.version> <curator-recipes.version>4.0.1</curator-recipes.version> <curator-framework.version>4.0.1</curator-framework.version> <zk.version>3.4.6</zk.version> <dubbo-version>2.7.6</dubbo-version> <spring-boot.version>2.2.6.RELEASE</spring-boot.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>${spring-boot.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>${spring-boot.version}</version> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> ... </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <skip>true</skip> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
需要说明的使用了聚合,那么父pom.xml 中的打包方式就一定是 pom , 就是这一句 :
<packaging>pom</packaging>
继承
而继承则是为了方便依赖的统一管理,例如 provider-bit 项目中的 pom.xml
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- 这里指明了父坐标,其中relativePath 指的是相对路径,最好是显式指明,默认是上一级的路径下--> <parent> <groupId>com.bbm</groupId> <artifactId>demo</artifactId> <version>1.0.0</version> <relativePath>../pom.xml</relativePath><!-- lookup parent from repository --> </parent> <artifactId>provider-bit</artifactId> <version>0.0.1-SNAPSHOT</version> <name>provider-bit</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>com.bbm</groupId> <artifactId>provider-api</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <!-- Dubbo Spring Boot Starter --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <exclusions> <exclusion> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <exclusions> <exclusion> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> <exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion> </exclusions> </dependency> <dependency> <artifactId>leaf-boot-starter</artifactId> <groupId>com.sankuai.inf.leaf</groupId> <version>1.0.1-RELEASE</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
我们会看到有部分依赖我们并没有指明版本,版本号是从父类中继承过来的,那么父类在哪里定义的呢?在 dependencyManagement 标签里,也就是父pom.xml 中的 :
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>${spring-boot.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>${spring-boot.version}</version> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> ... </dependencies> </dependencyManagement>
补充
说到 dependencyManagement 不得不提到依赖有一种范围 : import ,该依赖范围存在的动机就是解决依赖单继承的问题。我们上面讲的继承关系利用 dependencyManagement 可以维护统一的依赖版本,但是这样要是给多个项目继承的话,所管理的依赖非常多,有没有一种可以众多依赖中再提取一层出来。例如我的 provider-bit 项目需要依赖父类中 dependencyManagement 中定义的 aliyun-java-sdk-core ,然后我嫌 dependencyManagement 定义的依赖太多,太乱了,于是我把 aliyun-java-sdk-core 放到了另外一个项目中去 :
com.bbk 的common 项目中
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.bbk</groupId> <artifactId>otherparentpom</artifactId> <version>0.0.1-SNAPSHOT</version> <name>otherparentpom</name> <description>Demo project for Spring Boot</description> <packaging>pom</packaging> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <dependencyManagement> <!--定义在这里,当然还可以一定很多个--> <dependencies> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>4.0.6</version> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
然后在 provider-bit 中进行引用 :
<dependencies> <!--看这里,我想引入的依赖--> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- type 为 pom , scope 为 import 这就相当于多个继承了--> <dependency> <groupId>com.bbk</groupId> <artifactId>otherparentpom</artifactId> <version>0.0.1-SNAPSHOT</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
总结
本节主要介绍 maven 的聚合,继承和依赖范围为 import 的引入依赖。
参考
- https://www.infoq.cn/article/2011/01/xxb-maven-3-pom-refactoring
- http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html