我们看一个最常见到的例子:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
该例子表示你的project有一个junit dependency。你可能会问:这个dependency从哪里来?junit jar在哪里?
A dependency是对repository里的某个artifact的引用。POM定义了一个dependency,执行的时候就会根据dependency的groupId, artifactId and version,来search it from repository。你根本不需要在pom.xml里指明该dependancy来自哪个repository,maven会先查找local repository,如果local repository存在该dependancy引用的artifact,就使用它,如果不存在,则搜索所有你设置的remote repository,如果找到它,就把它download到local repository。缺省状态下,通常都是从central maven repository(http://www.ibiblio.org/maven2)来download artifact。如果你的pom.xml定义了多个remote repository,那么就按顺序依次试图从remote repository下载.
例如上面的例子,maven会先check local repository看是否有想要的junit artifact,如果没有,则从remote repository download到local repository。这时,local repository里artifact目录结构包含:
下图是在repository里所有artifact通用的目录结构:
groupId是fully qualified domain name,例如为x.y.z,则结构为:
maven是如何根据定义的dependancy来从repository里查找呢?例如上例,就会根据groupId “junit”, artifactId “junit”, and version “3.8.1”,在repository里查找~/.m2/repository/junit/junit/3.8.1/junit-3.8.1.jar。
dependancy功能是maven最强大的功能和最显著的优势。以前maven没出现之前,通常的project都会把要用到的jar files都放在project subdirectory下,或开发一个web app,你要把10多个jar添加到classpath,并把它们放到lib目录下。这样如果你开发100个类似的web app,你的每一个web app开发目录下面都会包含有这些jar files。这样如果某个jar的版本出现更新,就会要更新100个project里的jar。而使用maven,就会大大减轻你的工作量。
例如,你有100个web app都使用了spring 1.2.6 framework,如果你使用maven,你不需要存储所有的spring jars到各个project里,你只需要在POM.XML里定义一个spring dependancy,那么如果升级到spring 2.0,只需要把pom.xml里dependancy的<version>修改为2.0即可。
Dependency机制介绍
Dependency机制的三个知识点
- Transitive Dependencies
- Dependency Scope
- Dependency Management
Transitive Dependencies (可传递的依赖)
这是maven 2.0的新特征。它使你不需要指定dependency的位置而自动定位。而且可传递的依赖就是说依赖能够自动继承和传递,例如project A依赖project B的artifact,而project B则依赖project C的artifact,那么在build project A时,就会使用到所有project、子project的依赖。
一个project的依赖的总个数没有限制,但是如果出现死循环依赖则会出现问题。
由于依赖可以传递,因此有可能一个project要依赖的东东会很多,因此可以通过下列几种方式来限制要包括的dependency:
-
Dependency mediation – 意思是强烈建议显式设置你使用的dependency的版本号,因为dependency可能会有多种版本。目前Maven 2.0支持"nearest definition"(见下面的解释)。注意:如果在dependency tree的同一个depth里定义了同一个dependency的2个版本,那么使用先定义的那个版本。
-
"nearest definition" 表示在dependencies tree里最靠近你的project的版本。例如,如果project A的依赖性为:A -> B -> C -> D 2.0和A -> E -> D 1.0, 那么D的1.0版本将会被使用。因为从A通过E到达D的路径是最短的。如果本例你硬是想要使用D 2.0,那么你可以在A里定义一个D的dependency。
-
Dependency management – 表示maven允许你在你的pom.xml里设置你要使用的depedency的版本号,即使这个depedency你可能不知道是从哪里来的可传递依赖,也不知道该依赖定义的版本是什么,你都可以根据“nearest definition”法则来在你的pom.xml里设置版本号。例如上面的例子,你可以直接在A里设置对D的依赖(设置版本号),即使A并不直接使用D。
-
Dependency scope – 尽量为要包含的dependencies设置要用到它的scope。下面会详细解释
Dependency Scope
Dependency scope是设置什么stage要使用它,用来限制依赖的传递。
总共有5种Scopes:
-
compile – 这是缺省scope,表明是所有任务所需的资源。“Compile” dependencies are available in all classpaths.
-
provided – 表示该dependency是JDK部分或应用服务器的classpath里已经自带的资源,例如EJB的dependency jars,只需要在compile时使用,在例如打包时就不应该把它打包进jar, war or ear里,因为JDK or APP SERVER里本身就有。
-
runtime - this scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath.
-
test – 表示该dependency只会在test compilation and execution phases使用。例如在使用junit依赖时,scope参数的值为test来告诉Maven这个依赖项只是在测试阶段所需的,而不是运行时所需的资源。
-
system - this scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository. 后面会详细讲解
不同的scope会影响“依赖的依赖”的scope。下表列出的就是当一个“依赖”的scope设置为最左一列的scope,那么设置成最上一行scope的“依赖的依赖”的scope将发生的变化列表。
|
Compile
|
provided
|
runtime
|
test
|
compile
|
compile(*)
|
-
|
runtime
|
-
|
provided
|
Provided
|
provided
|
provided
|
-
|
runtime
|
Runtime
|
-
|
runtime
|
_
|
Test
|
Test
|
-
|
test
|
-
|
Dependency Management
在parent pom里使用< dependencyManagement>来简化dependency设置。举个例子:
Project A:
<project>
...
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>group-c</groupId>
<artifactId>excluded-artifact</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<type>bar</type>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
Project B:
<project>
...
<dependencies>
<dependency>
<groupId>group-c</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<type>war</type>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<type>bar</type>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
下面通过在parent pom里使用< dependencyManagement>来管理child pom要使用的dependencies。
Parent Project:
<project>
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>group-c</groupId>
<artifactId>excluded-artifact</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>group-c</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<type>war</type>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<type>bar</type>
<scope>runtime</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
使用上面parent pom就会简化child pom的dependency设置:
<project>
...
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
<!-- This is not a jar dependency, so we must specify type. -->
<type>bar</type>
</dependency>
</dependencies>
</project>
注意:在上面的dependency引用中,非jar的必须使用<type> element。
Dependency management的另一个很有用的用处就是控制dependency的版本。还是举例:
Project A:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>maven</groupId>
<artifactId>A</artifactId>
<packaging>pom</packaging>
<name>A</name>
<version>1.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>a</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>b</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>c</artifactId>
<version>1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>d</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Project B:
<project>
<parent>
<artifactId>A</artifactId>
<groupId>maven</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>maven</groupId>
<artifactId>B</artifactId>
<packaging>pom</packaging>
<name>B</name>
<version>1.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>d</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>maven-test</groupId>
<artifactId>a</artifactId>
<version>1.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>maven-test</groupId>
<artifactId>c</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
上面可以看出project A是project B的parent,A和B都定义a, c, d dependencies,那么如果对project B执行maven命令,会采用哪个定义的呢?答案如下:
-
dependency a and c将会采用1.0版本。尽管在parent project A里定义的a and d的版本是1.2,但根据dependency mediation "nearest definition"特性,采用的是project B定义的版本。
-
dependency b只在parent project A里有定义,因此就采用project A的定义。即使Dependency c会使用不同版本的b, 如果执行project B还是会采用project A定义的版本(还是根据dependency mediation "nearest definition"特性)。
-
dependency d的情况和dependency b的差不多:由于它在A和B都用定义,因此是采用project B定义的版本1.0。假如Dependency c会使用不同版本的d, 如果执行project B还是会采用project B定义的版本(还是根据dependency mediation "nearest definition"特性)。
System scope Dependency
System scope的dependencies总是available的,而且不需要从repository里获取,因为定义成system scope的dependencies都是由JDK or VM提供的。典型的例子就是JDBC standard extensions和Java Authentication and Authorization Service (JAAS).
例子:
<project>
...
<dependencies>
<dependency>
<groupId>javax.sql</groupId>
<artifactId>jdbc-stdext</artifactId>
<version>2.0</version>
<scope>system</scope>
<systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>
</dependencies>
...
</project>
如果你的artifact来自JDK's tools.jar,那么system path应该定义为:
<project>
...
<dependencies>
<dependency>
<groupId>sun.jdk</groupId>
<artifactId>tools</artifactId>
<version>1.5.0</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
...
</project>
分享到:
相关推荐
maven仓库所需要的jar包,包含完整的内容,可以去看一下简绍(https://blog.csdn.net/Fly_tom/article/details/81874197),由于csdn网站上传文件的限制,这个只是一部分,另一部分:...
If you are working with Java or Java EE projects and you want to take advantage of Maven dependency management, then this book is ideal for you. This book is also particularly useful if you are a ...
本文将详细介绍如何在Maven中增加自定义的repository。 首先,`settings.xml`是Maven的配置文件,位于用户目录下的`.m2`文件夹中(例如在Windows系统上是`%USER_HOME%\.m2\settings.xml`)。这个文件包含了Maven的...
Maven框架,本地jar资源仓,中央仓下载jar资源 有时在你的构建过程中,需要将第三方jar包添加到本地仓库中,因为它并存在于像Maven中央仓库或其它的公共仓库中。为了让Maven能够正确获取到jar包,第三方jar包必须...
maven-repository-metadata-3.0.jar
maven-dependency-plugin-2.8.jar
《Maven的Dependency详解》 在软件开发过程中,依赖管理是一项关键任务,尤其是在Java领域,Maven通过其强大的依赖管理...通过理解Dependency的配置和Repository的工作原理,开发者可以更好地利用Maven进行软件开发。
Maven repository.part1 for Java RESTful Web Service实战第二章需要的Mave库
"maven3.3.9+repository.zip" 提供的可能是 Maven 3.3.9 版本对应的仓库资源,这些资源包括了大量的第三方库,使得开发者无需手动管理依赖。 ** Maven 本地仓库 ** 本地仓库是每个开发者机器上默认的 Maven 存储...
《Doris 1.1.3 源码编译 Broker Maven 依赖包 Repository 深度解析》 Apache Doris 是一个高性能、分布式、在线分析处理(OLAP)的数据仓库系统,它提供了快速的数据查询能力,适用于大规模数据的实时分析。在Doris...
本文将聚焦于"Maven依赖插件"(maven-dependency-plugin)的版本2.8及其在开源项目中的应用,特别是结合Cobertura插件进行代码覆盖率检查。 Maven依赖插件(maven-dependency-plugin)是Maven生态系统中的一个重要...
**Maven的Dependency测试** 在Java开发中,Maven是一个不可或缺的构建工具,它通过管理项目的依赖关系,简化了项目的构建、编译和部署过程。本文将深入探讨Maven的Dependency测试方面,帮助开发者理解如何有效地...
5. Maven Repository 的作用 - 自动化依赖管理:Maven 通过仓库自动解决依赖关系,避免手动下载和管理 JAR 文件。 - 版本控制:仓库中的每个库都有版本号,便于版本控制和回滚,确保项目稳定。 - 代码复用:通过...
我们在IDEA的安装目录下找到 /plugins/maven/lib/maven2/conf 或者 /plugins/maven/lib/maven3/conf目录(如果两个都有建议都改掉),向其中的setting.xnl文件中的/标签下添加如下的仓库地址(这里以阿里云为例): ...
这个是maven的另一个部分jar,可以去看一下简绍(https://blog.csdn.net/Fly_tom/article/details/81874197),把这个文件下载完成,需要把它解压到maven-repository中的org文件下,一定是要点击右键解压到当前...
使用`mvn dependency:purge-local-repository`命令可以帮助清理这些无用的文件。 8. 仓库管理工具 对于大型企业,可能需要使用如Nexus或Artifactory这样的仓库管理工具,它们不仅可以作为私有远程仓库,还提供了...
【maven-repository 包】是一个集合了众多Java开发所需的Maven依赖的资源库,它极大地简化了开发者在构建项目时寻找和管理依赖的过程。在Java开发中,Maven是一个广泛应用的项目管理和集成工具,它负责管理项目的...
本篇文章将围绕"Maven-repository.zip"这个压缩包,深入探讨Maven的本地仓库、Maven安装以及项目模板的使用。 首先,我们来关注"Maven的本地仓库",即压缩包中的"repository.rar"。Maven的仓库是存储项目依赖的地方...
Maven repository.part1 for Java RESTful Web Service实战第二章需要的Mave库
Maven Dependency Helper安装Settings -> Plugins -> Marketplace, 搜索"Maven Dependency Helper"Settings -> Plugins -> Install plugin from disk快捷键Ctrl+Shift+D演示查询某一个依赖的版本信息通过搜索框搜索...