在命令行环境使用Maven
九、继承
1.概念
Maven工程之间,A工程继承B工程
- B工程:父工程
- A工程:子工程
本质上是A工程的pom.xml中的配置继承了B工程的pom.xml
2.作用
在父工程中统一管理项目中的依赖信息,具体来说是管理依赖的版本。
它的背景是:
- 对一个比较大型的项目进行了模块拆分
- 一个project下面,创建了很多个module
- 每一个module都需要配置自己的依赖信息
它背后的需求:
- 在每一个module中各自维护各自的依赖信息很容易发生出入,不易统一管理
- 使用同一个框架内的不同jar包,它们应该是同一个版本,所以整个项目中使用的框架版本需要统一
- 使用框架时所需要的jar包组合需要经过长期摸索和反复调试,最终确定一个可用组合。这个耗费很大精力总结出来的方案不应该在新的项目中重新摸索。
通过父工程中为整个项目维护依赖信息的组合,既保证了整个项目使用规范、准确的jar包,又能够将以往的经验沉淀下来,节约时间和精力。
3.举例
在一个工程中依赖多个spring的jar包
使用spring时要求所有Spring自己的jar包版本必须一致。为了能够对这些jar包的版本进行统一的管理,我们使用继承这个机制,将所有的版本信息统一在父工程中进行管理。
4.操作
①创建父工程
创建的过程和之前创建pro01-maven-java一样。
mvn archetype:generate
工程名称:pro03-maven-java
工程创建好之后,修改它的打包方式为pom
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sr.maven</groupId>
<artifactId>pro03-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
<!--意思是当前工程作为父工程 -->
<packaging>pom</packaging>
<name>pro03-maven-java</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
只有打包方式为pom的Maven工程能够管理其他Maven工程。打包方式为pom的Maven工程不参与业务代码,它是专门管理其他Maven工程的工程
②创建模块工程
模块工程类似于IDEA中module,所以需要进入pro03-maven-java工程的根目录,然后运行
mvn archetype:generate
创建模块工程,我们创建三个工程。
③查看被添加新内容的父工程pom.xml
这时候查看父工程pro03-maven-java的pom.xml,发现多了一些东西,多了最下面的modules和module标签。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sr.maven</groupId>
<artifactId>pro03-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>pro03-maven-java</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<!--聚合的配置-->
<modules>
<module>pro04-maven-module</module>
<module>pro05-maven-module</module>
<module>pro06-maven-module</module>
</modules>
</project>
④解读子工程的pom.xml
我们查看其中一个子工程的配置文件
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<!--通过指定父工程的坐标找到父工程-->
<parent>
<groupId>com.sr.maven</groupId>
<artifactId>pro03-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<!--子工程的groupId如果和父工程一样,则可以省略-->
<groupId>com.sr.maven</groupId>
<artifactId>pro04-maven-module</artifactId>
<!--子工程的version如果和父工程一样,则可以省略-->
<version>1.0-SNAPSHOT</version>
<name>pro04-maven-module</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
⑤在父工程中配置依赖的统一管理
在父工程的pom.xml中添加如下配置
<!--在父工程中统一管理依赖信息-->
<!--注意:并不是配置完如下,子工程就自动有如下依赖了,子工程还需要使用具体哪一个依赖的明确依赖-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
⑥子工程中引用那些被父工程管理的依赖
子工程需要添加被父工程管理的依赖:
情况1:版本号可以省略,使用的就是父工程管理的版本。
情况2:没有省略版本号,如果和父工程一样,还是采纳父工程的。若不同,则覆盖父工程的,采纳子工程的。
绝大部分情况下,子工程还是遵从父工程统一管理吧。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
⑦在父工程中升级依赖信息的版本
升级父工程4.0.0为4.1.0,直接修改父工程,子工程的依赖也会升级。
<!--在父工程中统一管理依赖信息-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
⑧在父工程中声明自定义属性
虽然上面升级版本已经能管理子工程了,但是还是要在父工程里改很多个地方。
这时候我们在父工程中使用properties标签
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--创建属于我们自己的属性-->
<!--标签名就是属性名,标签值就是属性值-->
<!--引用方式 ${标签名}}-->
<spring.version>4.1.0.RELEASE</spring.version>
</properties>
父工程中的依赖管理变为如下:
<!--在父工程中统一管理依赖信息-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
这样我们只需要修改properties中的版本值,就会控制所有属性所在的依赖版本。
5. 实际意义
编写一套符合要求、开发各种功能都能正常工作的依赖组合并不容易。如果公司里已经有人总结了成熟的组合方案,那么再开发新项目时,如果不再使用原有的积累,而是重新摸索,会浪费大量的时间。为了提高效率,我们可以使用工程继承的机制,让成熟的依赖组合方案能够保留下来。
如上图所示,公司级的父工程中管理的就是成熟的依赖组合方案,各个新项目、子系统各取所需即可。