Maven中的继承
实际开发中对一个比较大型的项目进行了模块拆分 , 一个project下面创建了很多个modul, 每一个module都需要配置自己的依赖信息
- 开发中使用的同一个框架内的不同jar包,它们应该是同一个版本,所以整个项目中使用的框架版本需要统一
传统方式: 在每一个module中各自维护各自的依赖信息, 这样很容易发生出入导致jar包的版本不易统一管理
- 确定使用框架时项目所需要的jar包组合(或者说依赖信息组合)需要经过长期摸索和反复调试耗费很大精力
Maven工程之间,A(子)工程继承B(父)工程 , 本质上是A工程的pom.xml中的配置继承了B工程中pom.xml的配置
- 一般在父工程中统一管理项目中的依赖信息,具体来说是管理依赖信息的版本
- 子工程就可以不用指定依赖的版本号 , 但必须往上可以追溯到一个父工程指定了依赖的版本号(不限于直接父工程)
- 一处修改处处生效 : 在父工程中将依赖信息的版本进行升级, 相应的所有子工程中依赖的版本号也会升级
编写一套符合要求、开发各种功能都能正常工作的依赖组合并不容易, 如果有人总结了成熟的组合方案,那么再开发新项目时就可以使用工程继承的机制
- 公司级的父工程中管理的就是保留下来的成熟的依赖组合方案,各个新项目、子系统各取所需即可,极大的提高了效率
- 通过在父工程中为整个项目维护依赖信息的组合既保证了整个项目使用规范准确的 jar包, 又能够将以往的经验沉淀下来,节约时间和精力
依赖版本管理
需求: 在一个工程中需要依赖多个Spring框架的jar包 , 要求工程中所有jar包的版本必须一致
[INFO] +- org.springframework:spring-core:jar:4.0.0.RELEASE:compile
[INFO] | \- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] +- org.springframework:spring-beans:jar:4.0.0.RELEASE:compile
[INFO] +- org.springframework:spring-context:jar:4.0.0.RELEASE:compile
[INFO] +- org.springframework:spring-expression:jar:4.0.0.RELEASE:compile
[INFO] +- org.springframework:spring-aop:jar:4.0.0.RELEASE:compile
[INFO] | \- aopalliance:aopalliance:jar:1.0:compile
第一步: 创建父工程pro03-maven-parent(工程中不写业务代码), 要修改它的打包方式为pom , 表示它是专门管理其他Maven工程的工程
<?xml version="1.0" encoding="UTF-8"?>
<!--project跟标签,表示对当前工程进行配置管理-->
<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标签:代表当前pom.xml所采用的标签结构,从Maven2开始就固定是4.0.0-->
<modelVersion>4.0.0</modelVersion>
<groupId>com.atguigu.maven</groupId>
<artifactId>pro03-maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!--当前工程作为父工程,它要去管理子工程,所以打包方式必须是pom-->
<packaging>pom</packaging>
<!--当前工程的名字-->
<name>pro03-maven-parent</name>
<!--maven的官网地址-->
<url>http://maven.apache.org</url>
<properties>
<!--工程构建过程中读取源码时使用的字符集-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
第二步: 创建子模块工程似于IDEA中的module, 需要进入pro03-maven-parent工程的根目录下运行mvn archetype:generate 命令来创建模块工程
- 创建完子模块工程后发现父工程pom.xml配置文件多了modules和module标签(聚合功能的配置)
- 子工程的pom.xml配置文件多了parent标签用来指定当前工程的父工程坐标
- 如果子工程引入依赖的jar包坐标中的groupId或version与父工程一致,那么可以省略groupId或version
<!--总工程中聚合的配置-->
<modules>
<module>pro04-maven-module</module>
<module>pro05-maven-module</module>
<module>pro06-maven-module</module>
</modules>
<!--使用parent标签指定当前工程的父工程-->
<parent>
<!--通过指定父工程的坐标找到父工程 -->
<groupId>com.atguigu.maven</groupId>
<artifactId>pro03-maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<!-- 如果子工程坐标中的groupId和version与父工程一致,那么可以省略它-->
<!-- <groupId>com.atguigu.maven</groupId> -->
<!-- <version>1.0-SNAPSHOT</version> -->
<artifactId>pro04-maven-module</artifactId>
第三步: 在父工程中使用dependencyManagement标签对依赖的版本号进行统一管理
- 被父工程管理的依赖并没有真正被引入到工程,子工程需要使用的依赖还需要手动配置到工程中但依赖信息可以不写版本号
- 如果子工程配置了依赖的版本号则以当前子工程的版本号为准(就近原则),一般子工程还是遵从父工程统一管理的依赖
<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>
第四步: 子工程中引用那些被父工程管理的依赖可以省略版本号, 表示子工程中这个依赖的版本由父工程的dependencyManagement决定
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
</dependencies>
在父工程中声明自定义属性
在父工程的properties标签内创建自定义属性标签用来统一指定依赖的版本,标签名即属性名,标签值即属性值
<!--自定义属性标签-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--创建自定义的属性标签-->
<atguigu.spring.version>4.3.6.RELEASE</atguigu.spring.version>
</properties>
通过${属性名}引用属性表达式的方式设定依赖的版本号, 这样所有的版本号就成了一个动态值,只有修改标签属性值相应的引用属性值的地方都会修改
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<!--引用自定义的属性名-->
<version>${atguigu.spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<!--引用自定义的属性名-->
<version>${atguigu.spring.version}</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>${atguigu.spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<!--引用自定义的属性名-->
<version>${atguigu.spring.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
Maven中的聚合
模块部分组成项目整体: 使用一个“总工程”将各个“模块工程”汇集起来,作为一个整体对应完整的项目
- 从继承关系角度来看:父工程和子工程
- 从聚合关系角度来看:总工程和模块工程
依赖循环: 如果A工程依赖B工程,B 程依赖C工程,C工程又反过来依赖A工程,那么在执行构建操作时会出现循环引用的错误
聚合的作用
Maven执行命令时要求有父工程时先安装父工程 , 有依赖的工程时,先安装被依赖的工程 , 工程聚合后执行命令时会自动按照正确的顺序执行
- 工程聚合之后可以一键执行Maven命令, 很多构建命令都可以在“总工程”中一键执行,如执行mvn install命令可以一键完成安装
- 在总工程配置聚合之后,各个模块工程会在总工程中展示一个列表,让项目中的各个模块一目了然
<!--在总工程/父工程pro03-maven-module中配置modules-->
<!--假设04依赖05,05依赖06(注意依赖循环问题),执行mvn install命令时安装顺序是03,06,05,04---->
<modules>
<module>pro04-maven-module</module>
<module>pro05-maven-module</module>
<module>pro06-maven-module</module>
</modules>