④. 如何解决依赖冲突
①. 使用maven提供的依赖调解原则
①. 依赖调节原则 — 第一声明者优先原则(在 pom 文件中定义依赖,以先声明的依赖为准。其实就是根据坐标导入的顺序来确定最终使用哪个传递过来的依赖)
结论:通过上图可以看到,spring-aop和spring-webmvc都传递过来了spring-beans,但是因为spring-aop在前面,所以最终使用的spring-beans是由spring-aop传递过来的,而spring-webmvc传递过来的spring-beans则被忽略了
②. 根据路径近者优先原则,
我们项目中引入的commons-logging为1.2
③. 如果在同一个pom中引入了两个相同的jar包,以引入的最后一个为准
如下的配置引入的是1.2
<dependencies> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> </dependencies>
②. 可选依赖optional
- ①. 新建项目A(类似于mysql)、B(类似于oracle),项目C(类似于业务层,引入A、B工程),项目D(类似于逻辑工程,引入了C)
C项目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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>mavenTest</artifactId> <groupId>com.xiaozhi</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>C</artifactId> <dependencies> <dependency> <groupId>com.xiaozhi</groupId> <artifactId>A</artifactId> <version>1.0-SNAPSHOT</version> <!-- optional=true,依赖不会传递,该项目依赖A 之后依赖该项目的项目如果想要使用A,需要重新引入 --> <optional>true</optional> </dependency> <dependency> <groupId>com.xiaozhi</groupId> <artifactId>B</artifactId> <version>1.0-SNAPSHOT</version> <optional>true</optional> </dependency> </dependencies> </project>
②. 画个图说明问题:
由于projectC使用到了两个来自projectA的类(OptionalFeatureAClass)和projectB的类(OptionalFeatureBClass).如果projectC没有依赖packageA和packageB,那么编译将会失败。
projectD依赖projectC,但是对于projectD来说,类(OptionalFeatureAClass)和类(OptionalFeatureBClass)是可选的特性,所以为了让最终的war/ejbpackage不包含不必要的依赖,使用optional声明当前依赖是可选的,默认情况下也不会被其他项目继承(好比Java中的final类,不能被其他类继承一样)
③. 如果projectD确实需要用到projectC中的OptionalFeatureAClass怎么办呢?
那我们就需要在projectD的pom.xml中显式的添加声明projectA依赖,继续看下图ProjectD需要用到ProjectA的OptionalFeatureAClass,那么需要在ProjectD的pom.xml文件中显式的添加对ProjectA的依赖
④. 到这也就很好理解为什么Maven为什么要设计optional关键字了,假设一个关于数据库持久化的项目(ProjectC),为了适配更多类型的数据库持久化设计,比如Mysql持久化设计(ProjectA)和Oracle持久化设计(ProjectB),当我们的项目(ProjectD)要用的ProjectC的持久化设计,不可能既引入mysql驱动又引入oracle驱动吧,所以我们要显式的指定一个,就是这个道理了
③. 排除依赖
- 可以使用exclusions标签将传递过来的依赖排除出去