一、创建父工程
创建的过程和前面创建普通工程 一样。
工程名称:pro03-maven-parent
工程创建好之后,要修改它的打包方式:
1
2
3
4
5
6
  | <groupId>com.atguigu.maven</groupId>
  <artifactId>pro03-maven-parent</artifactId>
  <version>1.0-SNAPSHOT</version>
  <!-- 当前工程作为父工程,它要去管理子工程,所以打包方式必须是 pom -->
  <packaging>pom</packaging>
  | 
有打包方式为 pom 的 Maven 工程能够管理其他 Maven 工程。打包方式为 pom 的 Maven 工程中不写业务代码,它是专门管理其他 Maven 工程的工程。
二、创建模块工程
模块工程类似于 IDEA 中的 module,所以需要进入 pro03-maven-parent 工程的根目录,然后运行 mvn archetype:generate 命令来创建模块工程。
假设,我们创建三个模块工程:

三、查看被添加新内容的父工程 pom.xml
下面 modules 和 module 标签是聚合功能的配置
1
2
3
4
5
  | <modules>  
	<module>pro04-maven-module</module>
	<module>pro05-maven-module</module>
	<module>pro06-maven-module</module>
</modules>
  | 
四、解读子工程的pom.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
  | <!-- 使用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> -->
<artifactId>pro04-maven-module</artifactId>
<!-- <version>1.0-SNAPSHOT</version> -->
  | 
五、在父工程中配置依赖的统一管理
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  | <!-- 使用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>
  | 
六、子工程中引用那些被父工程管理的依赖
关键点:省略版本号
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  | <!-- 把版本号去掉就表示子工程中这个依赖的版本由父工程决定。 -->
<!-- 具体来说是由父工程的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>
  | 
七、在父工程中声明自定义属性
1
2
3
4
5
6
7
  | <properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	
	<!-- 自定义标签,维护Spring版本数据 -->
  <!-- 通过自定义属性,统一指定Spring的版本 -->
	<atguigu.spring.version>4.3.6.RELEASE</atguigu.spring.version>
</properties>
  | 
在需要的地方使用${}的形式来引用自定义的属性名:
1
2
3
4
5
  | 			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-core</artifactId>
				<version>${atguigu.spring.version}</version>
			</dependency>
  | 
真正实现“一处修改,处处生效”。
八、实际意义

编写一套符合要求、开发各种功能都能正常工作的依赖组合并不容易。如果公司里已经有人总结了成熟的组合方案,那么再开发新项目时,如果不使用原有的积累,而是重新摸索,会浪费大量的时间。为了提高效率,我们可以使用工程继承的机制,让成熟的依赖组合方案能够保留下来。
如上图所示,公司级的父工程中管理的就是成熟的依赖组合方案,各个新项目、子系统各取所需即可。
实验 多重继承:
1、aaa项目:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
  | 		<groupId>org.example</groupId>
    <artifactId>aaa</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.javassist</groupId>
                <artifactId>javassist</artifactId>
                <version>3.24.1-GA</version>
            </dependency>
            <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>24.0-jre</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
  | 
2、bbb项目继承aaa项目:
重新定义 javassist的版本
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
  | 		<parent>
        <groupId>org.example</groupId>
        <artifactId>aaa</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
		<modelVersion>4.0.0</modelVersion>
    <artifactId>bbb</artifactId>
    <packaging>pom</packaging>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.javassist</groupId>
                <artifactId>javassist</artifactId>
                <version>3.28.0-GA</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
  | 
3、ccc项目继承bbb项目:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
  | 		<parent>
        <groupId>org.example</groupId>
        <artifactId>bbb</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>ccc</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
        </dependency>
    </dependencies>
  | 
4、发现
这时 执行 mvn dependency:tree 发现:
1、javassist的版本是bbb项目定义的版本,被覆盖了;
2、guava的版本还是aaa项目的版本;
3、并且当修改aaa项目的guava版本,aaa项目内 mvn install 后,在ccc项目中重新加载后,发现guava版本也随之更改,这时就跟bbb项目的状态无关。
tip:
在bbb项目虽然是pom的打包格式,但是也可以写dependencies,直接依赖jar包,和dependencyManagement分别做两件事,不会出错