目录
1.Maven继承的实现以及统一版本
maven可以由很多的工程组成,那么要如何统一每个工程所用到的jar包都是同一个版本呢,例如A,B两个工程,A用Junit4,B用Junit3.8,要合成一个项目时会不会出问题呢?(例子不一定严谨,大致这个意思)
好处:解决模块之间jar包冲突问题
实现步骤:
1.1 建立父工程: 父工程的打包方式为pom
注意1:打包方式有三种
java工程——jar
web项目-war
父工程-pom
注意2:这里HelloWorld2是其子工程,打包方式为jar,目录结构显然不一样,因为父工程相当于一个接口,只需声明一下,无须实现
1.2 在父工程的pom.xml中编写依赖:
<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>org.lanqiao.maven</groupId>
<artifactId>HelloWorldFather</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<!-- 父工程,父工程的依赖的写法 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
1.3 配置子类:
给当前工程 继承一个父工程:1加入父工程座标gav 2当前工程的Pom.xml到父工程的Pom.xml之间的 相对路径 -->
<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>org.lanqiao.maven</groupId> -->
<artifactId>HelloWorld2</artifactId><!-- gouupid和version可以继承父类而来,就artifactId不能省 -->
<!-- <version>0.0.1-SNAPSHOT</version> -->
<!-- 给当前工程 继承一个父工程:1加入父工程座标gav 2当前工程的Pom.xml到父工程的Pom.xml之间的 相对路径 -->
<parent>
<!-- 1.给当前工程 继承一个父工程:1加入父工程座标gav -->
<groupId>org.lanqiao.maven</groupId>
<artifactId>HelloWorldFather</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!--2当前工程的Pom.xml到父工程的Pom.xml之间的 相对路径 -->
<relativePath>../HelloWorld2/pom.xml</relativePath>
</parent>
</project>
注意:此时按理说已经完事,但是父工程可能有非常多的依赖,子工程若是像子类必须实现所继承接口里面的所有声明一样,那子工程必然会引入非常多根本用不着的jar包,所以这里就设置为只有在子工程声明我要用到这个依赖才会继承父类的
1.4 在子类中 需要声明 :加上使用哪些父类的依赖
<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>org.lanqiao.maven</groupId> -->
<artifactId>HelloWorld2</artifactId><!-- gouupid和version可以继承父类而来,就artifactId不能省 -->
<!-- <version>0.0.1-SNAPSHOT</version> -->
<!-- 给当前工程 继承一个父工程:1加入父工程座标gav 2当前工程的Pom.xml到父工程的Pom.xml之间的 相对路径 -->
<parent>
<!-- 1.给当前工程 继承一个父工程:1加入父工程座标gav -->
<groupId>org.lanqiao.maven</groupId>
<artifactId>HelloWorldFather</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!--2当前工程的Pom.xml到父工程的Pom.xml之间的 相对路径 -->
<relativePath>../HelloWorld2/pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<!-- 声明需要使用到父类的Junit(只用ga,无需version) -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
</project>
这样一来就好了,要验证是否成功,保存更新后可以先点Effective POM,可以看见父类的Junit的版本信息已经被子类继承了。
2 对maven依赖关系的理解
若B依赖于A,B想要编译成功,必须把A放入仓库。
原因是所有的类实际上用的是都是仓库里的同一份jar包,并不是副本,也就是说自身引入的jar包实际上只是对应仓库里jar包的映射名字而已,如图
我若想导入A这个jar包,实际上也并不是真的导入,而是对仓库里那唯一的一份 A jar包的映射(也可以这样理解,若有成千上百的项目要用A这个jar包,不需要每个都复制一份A jar包,而是公用一份),这就是为啥若A依赖于B ,必须把A放入仓库,然后A要用B,只需提供B的gav就好。
好,进一步来深化问题。
假如A是B的父工程,C又依赖于B,那么C若想编译成功,必须同时把A与B放入仓库。
先假设A本身有一个依赖junit
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
<scope>compile</scope>
</dependency>
B继承A后,又扩展了一个依赖commons-io(故B共有junit和commons-io两个依赖)
<parent>
<!-- 1.给当前工程 继承一个父工程:1加入父工程座标gav -->
<groupId>org.lanqiao.maven</groupId>
<artifactId>A</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../A/pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<!-- 声明需要使用到父类的Junit(只用ga,无需version) -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
C依赖于B,自身无拓展(故C共有junit和commons-io两个依赖)
<dependencies>
<dependency>
<groupId>org.lanqiao.maven</groupId>
<artifactId>B</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
现在若想C编译成功,先通过B的gav找到B所提供的jar(所以B需要放入仓库),而B又要知道A所提供的jar(所以A需要放入仓库)。若只放了B没放A,那么就只能找到commons-io而找不到junit。
还有一个需要注意的是,若是直接在C中加了junit的依赖,虽然C中的Junit会覆盖A中的Junit,但是经验证还是得把A放入仓库。
总而言之,只要是被某个项目所依赖的统统都要加入仓库中。
3 maven聚合
基于对继承和依赖的理解,那么聚合就比较容易了,它只做一件事,就是把一个子项目所依赖的所有父项目一起compile,test,package,install,无需我们关心先后顺序。比如B依赖A,现在想compile B成功,那么我们必须先手工install A,如果项目很多的时候就会理不清各自依赖的先后顺序,此时用聚合这个一键话操作就会十分便利
类似写法如下,注意聚合项目的打包方式必须为pom
总结
我觉得继承和依赖想做的事比较像,都是把自己已经标注的jar包的位置传给他们的后代用,而后代若想用父代提供的jar包位置信息,必须把父代先打包放入仓库,以此类推。在这个嵌套关系很深的情况下就很难理清各自的依赖先后关系,这时聚合的强大就体现出来了,我们只需在聚合里声明想操作的子代的所有上一级父代(包括父代的父代........),就无需理会父类的先后关系了。