Maven Dependency

2024-04-27 10:48
文章标签 maven dependency

本文主要是介绍Maven Dependency,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 我们看一个最常见到的例子:
<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>
 
 
 
Repository介绍
 
Artifact Repositories
Repository就是用来存储artifacts and dependencies(实质也就是artifact)的地方。
有2种类型的repositories: local and remote。local repository里存储了因有使用需要而从remote repository下载的artifacts 的cache,还存储了你在本地build的,但还没有发布到remote repository的artifacts。
Remote repositories能够被accessed by 各种协议(如file:// and http://)。Remote repositories可以是真正供所有人都可以进入的repositorie(例如:Maven's central repository  repo1.maven.org就是典型例子),也可以是一个build在你公司内部http server的internal repositories,它只在你们的开发团队里共享。
The local and remote repositories的结构是相同的,但作为maven的使用者,我们不需要去深入了解它的结构。
 
Why not Store JARs in CVS?
Maven强烈建议不要在你的project里包含任何要引用的JARs,即project不要存储这些jars,而应该定义对这些jars的dependency。例如,很多的project都会使用到一些常用的jar(如junit, XML parsers和standard utilities),你不要把他们的jar都放入你的project里,而应该使用它们的dependencies。
这些dependencies存储在local repositoty里可以供成千上万个project使用,其好处有:
·         It uses less storage – 每个JAR只存储在repository一个地方,所有的project如果要使用它就定义它的dependency即可,节约了空间,同时也使你的project cleaner。
·         It makes checking out a project quicker - initial checkout, and to a small degree updating, a project will be faster if there are no large binary files in CVS. While they may need to be downloaded again afterwards anyway, this only happens once and may not be necessary for some common JARs already in place.
·         No need for versioning – CVS and other source control systems are designed for versioning files, but external dependencies typically don't change, or if they do their filename changes anyway to indicate the new version. Storing these in CVS doesn't have any added benefit over keeping them in a local artifact cache.
 
Using Repositories
通常,你不需要对local repository做任何事,除非你想重新download所有的artifact而清空local repository
而对于remote repositories, 它们是用来download and upload artifact的 (当然,你必须有权限才可以操作).
Downloading from a Remote Repository
当一个project定义的dependency 在local repository里找不到,或者remote repository包含了新版本时,就会激活Download the dependency from remote repository的操作。
缺省情况下,会从maven central repository (http://repo1.maven.org/maven2 ) 下载。如果你还希望能够从其他的remote repository下载(比如要下载只供你们team使用的artifact),你需要在POM.XML里做下列设置:
<project>
 ...
 <repositories>
    <repository>
      <id>my-internal-site</id>
      <url>http://myserver/repo</url>
    </repository>
 </repositories>
 ...
</project>
上述设置也可以在settings.xml里。
Using Mirrors for the Central Repository
就象web server一样,central repository有时也会down机。如果这种情况发生了,你可以在settings.xml 里设置 <mirrors> element。详见Using Mirrors for Repositories .
 
Build Offline
如果你在使用maven build project时你的电脑无法连上网,那么你可以在mvn命令里添加-o参数
 mvn -o package
但要注意:许多plugins在设置为offline的情况下不会执行任何需要连接上网的操作,就会导致失败。
 
Internal Repositories
 
对于团队合作开发的project,建一个internal repository,使得团队成员能够共享、下载、上传最新的artifact,是非常必要的。internal repository并没有什么特别,它实际上就是一个remote repository
团队成员可以使用HTTP or the file system (using a file:// URL)的方式从internal repository下载artifact,也可以使用 SCP, FTP, or a file copy的方式上传artifact到internal repository。
之后会有一篇文章专门讲如何set up, use and deploy internal repository.

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/totogogo/archive/2007/12/20/1956381.aspx

这篇关于Maven Dependency的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/940298

相关文章

CentOS系统Maven安装教程分享

《CentOS系统Maven安装教程分享》本文介绍了如何在CentOS系统中安装Maven,并提供了一个简单的实际应用案例,安装Maven需要先安装Java和设置环境变量,Maven可以自动管理项目的... 目录准备工作下载并安装Maven常见问题及解决方法实际应用案例总结Maven是一个流行的项目管理工具

使用maven依赖详解

《使用maven依赖详解》本文主要介绍了Maven的基础知识,包括Maven的简介、仓库类型、常用命令、场景举例、指令总结、依赖范围、settings.xml说明等,同时,还详细讲解了Maven依赖的... 目录1. maven基础1.1 简介1.2 仓库类型1.3 常用命令1.4 场景举例1.5 指令总结

SpringBoot项目中Maven剔除无用Jar引用的最佳实践

《SpringBoot项目中Maven剔除无用Jar引用的最佳实践》在SpringBoot项目开发中,Maven是最常用的构建工具之一,通过Maven,我们可以轻松地管理项目所需的依赖,而,... 目录1、引言2、Maven 依赖管理的基础概念2.1 什么是 Maven 依赖2.2 Maven 的依赖传递机

关于Maven生命周期相关命令演示

《关于Maven生命周期相关命令演示》Maven的生命周期分为Clean、Default和Site三个主要阶段,每个阶段包含多个关键步骤,如清理、编译、测试、打包等,通过执行相应的Maven命令,可以... 目录1. Maven 生命周期概述1.1 Clean Lifecycle1.2 Default Li

关于Maven中pom.xml文件配置详解

《关于Maven中pom.xml文件配置详解》pom.xml是Maven项目的核心配置文件,它描述了项目的结构、依赖关系、构建配置等信息,通过合理配置pom.xml,可以提高项目的可维护性和构建效率... 目录1. POM文件的基本结构1.1 项目基本信息2. 项目属性2.1 引用属性3. 项目依赖4. 构

springboot 加载本地jar到maven的实现方法

《springboot加载本地jar到maven的实现方法》如何在SpringBoot项目中加载本地jar到Maven本地仓库,使用Maven的install-file目标来实现,本文结合实例代码给... 在Spring Boothttp://www.chinasem.cn项目中,如果你想要加载一个本地的ja

每天认识几个maven依赖(ActiveMQ+activemq-jaxb+activesoap+activespace+adarwin)

八、ActiveMQ 1、是什么? ActiveMQ 是一个开源的消息中间件(Message Broker),由 Apache 软件基金会开发和维护。它实现了 Java 消息服务(Java Message Service, JMS)规范,并支持多种消息传递协议,包括 AMQP、MQTT 和 OpenWire 等。 2、有什么用? 可靠性:ActiveMQ 提供了消息持久性和事务支持,确保消

30常用 Maven 命令

Maven 是一个强大的项目管理和构建工具,它广泛用于 Java 项目的依赖管理、构建流程和插件集成。Maven 的命令行工具提供了大量的命令来帮助开发人员管理项目的生命周期、依赖和插件。以下是 常用 Maven 命令的使用场景及其详细解释。 1. mvn clean 使用场景:清理项目的生成目录,通常用于删除项目中自动生成的文件(如 target/ 目录)。共性规律:清理操作

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定

maven 编译构建可以执行的jar包

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」👈,「stormsha的知识库」👈持续学习,不断总结,共同进步,为了踏实,做好当下事儿~ 专栏导航 Python系列: Python面试题合集,剑指大厂Git系列: Git操作技巧GO