dependencyManagementy与dependencies的区别

在 pom 中指明 dependency management 元素的方式maven 结合项目继承来管理依赖。

在多模块应用中,可能多个子项目会有共同的依赖。此时为了正确运行,必须让所有的子项目使用依赖项的同一版本。必须确保应用的各个项目的依赖项和版本一致,才能保证测试的和发布的是相同的成果。因此,应在顶层的 pom 中定义共同的依赖关系。

比如有的依赖的<scope>是写在子项目中的 <dependencies> 下的<dependency> 标签中, 
而有的依赖的<scope>是写在父项目中的<dependencyManagement> 中 。 
我知道前一种写法是对的,而后一种写法却不知道对不对了,从网上查了下,没有找到非常确切的答案,于是自己验证了一把。 
把验证过程给大家说下,大家也可以自己练手。 
首先新建三个项目,Parent作为父项目、projectA、projectB作为子项目。 
在父项目Parent中依赖项如下: 

<dependencies> 
<dependency> 
<groupId>junit</groupId> 
<artifactId>junit</artifactId> 
<version>4.8.1</version> 
<scope>test</scope> 
</dependency> 
</dependencies>

 
在子项目projectA、projectB中没有写任何依赖,在projectA 下运行命令 mvn help:effective-pom,会发现A下面有 junit 4.8.1的依赖。 

如果我把 父项目Parent 中的依赖修改如下: 

<dependencyManagement> 
<dependencies> 
<dependency> 
<groupId>junit</groupId> 
<artifactId>junit</artifactId> 
<version>4.8.1</version> 
<scope>test</scope> 
</dependency> 
</dependencies> 
</dependencyManagement>

 子项目ProjectA、projectB下面还是没有任何依赖项,在projectA 下运行命令 mvn help:effective-pom,会发现A下面 没有 junit 4.8.1的依赖。 
如果我在projectA 下添加junit的依赖: 

<dependencies> 
<dependency> 
<groupId>junit</groupId> 
<artifactId>junit</artifactId> 
</dependency> 
</dependencies>

 再在projectA 下运行命令 mvn help:effective-pom,会发现A下面有了 junit 4.8.1的依赖,并且scope为 test。 
那么经过验证,scope写在子项目中的<dependencies> 下的<dependency>中,或是写在父项目中的<dependencyManagement>中,都是可以的。 
但有一点需要注意,dependencies 和 dependencyManagement 的区别在于: 
dependencies中,即使在子项目中不写该依赖项,那么子项目仍然会从父项目中继承该依赖项。 
dependencyManagement 中,如果在子项目中不写该依赖项,那么子项目中是不会从父项目继承该依赖项的;只有在子项目中写了该依赖项,才会从父项目中继承该项,并且version 和 scope 都读取自 父pom,这样就可以保证所有版本一致了。 

注意:一个是项目依赖,一个是多模块maven项目时候的依赖管理控制的。

-------------------------------- 

可以在父模块中配置如下: 

<dependencyManagement> 
<dependencies> 
<dependency> 
<groupId>junit</groupId> 
<artifactid>junit</artifactId> 
<version>4.8.2</version> 
<scope>test</scope> 
</dependency> 
<dependency> 
<groupId>log4j</groupId> 
<artifactid>log4j</artifactId> 
<version>1.2.16</version> 
</dependency> 
</dependencies> 
</dependencyManagement>

 
这段配置不会给任何子模块引入依赖,但如果某个子模块需要使用JUnit和Log4j的时候,我们就可以简化依赖配置成这样:  

<dependency> 
<groupId>junit</groupId> 
<artifactid>junit</artifactId> 
</dependency> 
<dependency> 
<groupId>log4j</groupId> 
<artifactid>log4j</artifactId> 
</dependency>

 
现在只需要groupId和artifactId,其它元素如version和scope都能通过继承父POM的dependencyManagement得到。

如果有依赖配置了exclusions,那节省的代码就更加可观。但重点不在这,重点在于现在能够保证所有模块使用的JUnit和Log4j依赖配置是一致的。而且子模块仍然可以按需引入依赖,如果我不配置dependency,父模块中dependencyManagement下的spring-aop依赖不会对我产生任何影响。 

也许你已经意识到了,在多模块Maven项目中,dependencyManagement几乎是必不可少的,因为只有它是才能够有效地帮我们维护依赖一致性。 

使用dependencyManagement还有另外一种方式,那就是我们可以不从父模块继承,而是使用特殊的import scope依赖。
我们知道Maven的继承和Java的继承一样,是无法实现多重继承的,如果10个、20个甚至更多模块继承自同一个模块,那么按照我们之前的做法,这个父模块的dependencyManagement会包含大量的依赖。如果你想把这些依赖分类以更清晰的管理,那就不可能了,import scope依赖能解决这个问题。你可以把dependencyManagement放到单独的专门用来管理依赖的POM中,然后在需要使用依赖的模块中通过import scope依赖,就可以引入dependencyManagement。例如可以写这样一个用于依赖管理的POM: 

<project> 
<modelVersion>4.0.0</modelVersion> 
<groupId>com.juvenxu.sample</groupId> 
<artifactId>sample-dependency-infrastructure</artifactId> 
<packaging>pom</packaging> 
<version>1.0-SNAPSHOT</version> 

<dependencyManagement> 
<dependencies> 
<dependency> 
<groupId>junit</groupId> 
<artifactid>junit</artifactId> 
<version>4.8.2</version> 
<scope>test</scope> 
</dependency> 
<dependency> 
<groupId>log4j</groupId> 
<artifactid>log4j</artifactId> 
<version>1.2.16</version> 
</dependency> 
</dependencies> 
</dependencyManagement> 

</project>

 
然后我就可以通过非继承的方式来引入这段依赖管理配置: 
 

<dependencyManagement> 
<dependencies> 
<dependency> 
<groupId>com.juvenxu.sample</groupId> 
<artifactid>sample-dependency-infrastructure</artifactId> 
<version>1.0-SNAPSHOT</version> 
<type>pom</type> 
<scope>import</scope> 
</dependency> 
</dependencies> 
</dependencyManagement> 

<dependencies>
<dependency> 
<groupId>junit</groupId> 
<artifactid>junit</artifactId> 
</dependency> 
<dependency> 
<groupId>log4j</groupId> 
<artifactid>log4j</artifactId> 
</dependency> 
</dependencies>

 
这样,父模块的POM就会非常干净,由专门的packaging为pom的POM来管理依赖,也契合的面向对象设计中的单一职责原则。此外,我们还能够创建多个这样的依赖管理POM,以更细化的方式管理依赖。这种做法与面向对象设计中使用组合而非继承也有点相似的味道。

  

 参考URL

相关推荐