maven的几种maven引入依赖无法范围

Maven管理(依赖范围,依赖传递,依赖冲突,依赖可选,依赖排除)
Maven管理:
1. 依赖范围
maven的依赖范围有4种, 分别是:
compile: 对主代码有效,
对测试代码有效,
被打包运行时有效.
对主代码无效,
对测试代码有效,
被打包运行时无效.
provided: 对主代码有效,
对测试代码有效,
被打包运行时无效.
对主代码无效,
对测试代码无效,
被打包运行时有效.
其中依赖范围用scope 来控制和编译,测试,运行的classpath的关系.
2. 依赖传递
这里举个例子:
现在有三个工程项目, 分别是A, B, C,
其中B工程依赖了A工程, C工程依赖了B工程,
那么, A,B工程分别就是B,C工程的直接依赖,BC为第一直接依赖,AB为第二直接依赖, 而A工程就是C工程的间接依赖,
所依赖工程中pom.xml可以传递下去,
当第二依赖的范围scope 为compile 的时候, 依赖得以传递,传递性依赖的范围与第一直接依赖的范围一致.
当第二依赖的范围scope 为test 的时候, 依赖不会得以传递.
当第二依赖的范围是provided的时候,只传递第一直接依赖范围也为provided的依赖,且传递性依赖的范围同样为 provided.
当第二直接依赖的范围是runtime的时候,传递性依赖的范围与第一直接依赖的范围一致,但compile例外,此时传递的依赖范围为runtime.
3. 依赖冲突
maven的依赖冲突可以分为两种, 一种是跨pom的冲突,
另外一种就是同一个pom.xml 文件的冲突.
现在A工程的pom.xml 中依赖了junit4.9 的版本, 则B,C工程中都是使用了junit4.9 的版本.
1). 跨pom.xml的冲突:
如果B工程中的pom.xml 重新依赖了junit4.8 的版本,
那么,工程B, C就都会使用junit4.8 的版本.
2). 同一个pom.xml的冲突:
如果在A工程中先依赖了junit4.9的版本, 然后下面又在依赖了junit4.8 的版本, 那么,按照就近原则,越下面越近, 最后使用的是junit4.8 的版本.
总结: maven的依赖如果发生了冲突, 服从就近原则.
4.依赖可选
pom.xml文件中, Optional标签表示该依赖是否可选,默认是false。如果为true,则表示该依赖不会传递下去,如果为false,则会传递下去。
5.依赖排除
pom.xml文件中,Exclusions标签可以排除依赖.
例如: 在C工程中排除掉A工程依赖
&dependencies&
&dependency& &groupId&com.c.maven&/groupId& &artifactId&C&/artifactId& &version&0.0.1-SNAPSHOT&/version& &exclusions&
&exclusion&
&groupId&com.a.maven&/groupId&
&artifactId&A&/artifactId&
&/exclusion& &/exclusions&
&/dependency&
&/dependencies&
以上就是小编对maven管理的理解, 希望对大家有所帮助!!!
Maven的排除依赖、归类依赖、优化依赖
Maven的传递性依赖及其jar包冲突解决
【maven】--依赖管理
maven的依赖传递性讲解
Maven 依赖范围、依赖传递、排除依赖
【Maven】菜鸟入门Maven遇到的坑--添加依赖关系
maven工程中因为依赖产生的各种问题汇总
Maven使用总结(二):Maven依赖配置
maven依赖总结
没有更多推荐了,同步各端记录
下载PC客户端,上传视频更轻松!
药品服务许可证(京)-经营-
请使用者仔细阅读优酷、、
Copyright(C)2017 优酷 youku.com 版权所有
不良信息举报电话:
3 maven的依赖范围和依赖传递策略
3 maven的依赖范围和依赖传递策略—在线播放—《3 maven的依赖范围和依赖传递策略》—科技—优酷网,视频高清在线观看
微信/手机 扫码分享
点击一下 网页分享
<input id="link4" type="text" class="fn-share-input" value="" data-spm-anchor-id="0.0.0.i1" />
复制通用代码
<input type="text" class="fn-share-input" id="link3" value="" />
复制Html代码
复制Flash代码
抱歉!因版权原因无法下载
superstar肚皮舞
用优酷移动APP扫码
或用微信扫码观看
二维码2小时有效
没有客户端?扫码马上安装
IPHONE / 安卓
superstar肚皮舞
使用HTML5播放器
使用FLASH播放器1、何为Maven坐标
Maven定义了这样一组规则:世界上任何一个构建都可以使用Maven坐标唯一标示,Maven坐标的元素包括groupId、artifactId、version、packaging、classifier。只要提供正确的坐标元素,Maven就能找到对应的构建。
2、坐标详解
详细解释一下各个坐标元素
groupId:定义当前Maven项目隶属的实际项目,通常以域名反向对应
artifactId:该元素定义实际项目中的一个Maven项目(模块),在默认情况下,Maven生成的构建,其文件名会以artifactId作为开头。
version:版本
packaging:定义Maven的打包方式
classifier:不可直接定义,因为附属构件不是项目直接默认生成的,而是又附加的插件帮助生成。
项目的构件名是与坐标相对应的,一般的规则为artifactId-version[-classifier].packaging,[-classifier表示可选]。
3、依赖的配置
一个依赖声明可以包含如下的一些元素:
&dependencies&
&dependency&
&groupId&...&/groupId&
&artifactId&...&/artifactId&
&version&...&/version&
&type&...&/type&
&optional&...&optional&
&exclusions&
&exclusion&...&/exclusion&
&/exclusions&
&/dependency&
&/dependencies&
&/project&
根元素下可以dependencies可以包含一个或者多个dependency元素,以声明一个或者多个项目依赖。每个依赖可以包含的 元素有:
groupId、artifactId和version:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,Maven根据坐标才能找到需要的依赖。
type:依赖的类型,对应于项目坐标定义的packaging。大部分情况下,该元素不声明,其默认值为jar
scope:依赖的范围,默认为compile。也可设置为test
optional:标记依赖是否可选
exclusions:用来排除传递性依赖。
4、依赖范围
依赖范围用来控制依赖与这三种classpath(编译classpath、测试classpath、运行classpath)的关系,Maven有一下几种依赖范围:
compile:编译依赖范围。如果没有指定,就会默认使用该依赖范围,使用此依赖范围的Maven依赖,对于编译、测试、运行三种classpath都有效。
test:测试依赖范围。使用该范围的Maven依赖,只对于测试classpath有效,在编译主代码或者运行项目的使用时将无法使用此类依赖。典型的例子是JUnit,它只是在编译测试代码和运行测试的时候需要该依赖。
provided:已提供依赖范围。使用此依赖范围的Maven依赖,对于编译和测试的classpath有效,但是在运行时无效。典型的例子是servlet-api,编译和测试项目的时候需要改依赖,但是在运行项目的时候,由于容器已经提供,就不需要Maven重复地引入一遍。
runtime:运行时依赖范围。使用此依赖范围的Maven依赖,对于测试和运行classpath有效,但是编译主代码时无效。典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在测试或者运行项目的时候才需要实现上述接口的JDBC驱动。
system:系统依赖范围,该范围与三种classpath的关系,和provided依赖范围完全一致。但是,使用system范围的依赖时必须通过systemPath元素显式的指定依赖文件的路径。由于此类依赖不是通过Maven仓库解析,而且往往与本机系统绑定,可能造成构建的不可移植,因此需要谨慎使用。systemPath元素可以引用环境变量,如:
&dependency&
&groupId&javax.sql&/groupId&
&artifactId&jdbc-stdext&/artifactId&
&version&2.0&/version&
&scope&system&/scope&
&systemPath&${java.home}/lib/rt.jar&/systemPath&
&/dependency&
Import(Maven 2.0.9及以上):导入依赖范围。该依赖范围不会对三种classpath产生实际的影响
上述除了import以外的各种依赖范围与三种classpath的关系如下表所示:
spring-core
servlet-api
JDBC驱动实现
本地的,Maven仓库之外的类库文件
5、传递性依赖
何为传递性依赖
实际开发中,我们会需要用到很多项目所依赖的jar包,例如,我们公司的feishu系统依赖Spring Framework,Spring Framework又依赖于commons-logging,那么commons-logging就是feishu的传递性依赖。Maven会解析各个直接依赖的POM,将那些必要的间接依赖,以传递性依赖的形式引入到当前的项目当中
传递性依赖和依赖范围
依赖范围不仅可以控制依赖于三种classpath的关系,还对传递性依赖产生影响。假设A依赖于B,B依赖于C,我们说A对于B是第一直接依赖,B对C是第二直接依赖,A对C是传递性依赖。第一直接依赖的范围和第二直接依赖的范围决定了传递性依赖的范围,下表所示,最左边一列表示第一直接依赖范围,最上面一行表示第二直接依赖范围,中间交叉单元格则表示传递性依赖范围。
6、依赖调解
Maven引入的传递性依赖,一方面大大简化了和方便了依赖声明,另一方面,大部分情况下我们只关心项目的直接依赖是什么,而不用考虑这些依赖会引入什么传递性依赖。但是有时候当传递性依赖造成问题的时候,我们就需要清楚的知道传递性依赖是从那条依赖路径引入的。
第一原则:路径最近者优先
例如,项目A有这样的依赖:
A--&B--&C--&X(1.0)
A--&D--X(2.0)
根据第一原则,选择路径最近的,所以X(2.0)会被解析使用。
第二原则:第一声明者优先
依赖调解的第一原则不能解决所有问题,例如:
A--&B--&Y(1.0)
A--&C--&Y(2.0)
当遇到路径长度相同的情况,第一原则已经不能判断解析谁了,那么更加依赖调解的第二原则,选择第一声明者,假如在POM中先声明B,那么Y(1.0)会被解析使用。
7、可选依赖
假设,项目A依赖于项目B,项目B依赖于项目X和Y,B对于X和Y的依赖都是可选依赖:A--&B、B--&X(可选)、B--&Y(可选),根据传递性依赖的定义,如果所有这三个依赖的范围都是compile,那么X、Y就是A的compile范围传递性依赖,然而不是这样的,==由于X、Y是传递性依赖、依赖将不会被传递==。换句话说,X、Y将不会对A有任何影响。
为什么要使用可选依赖这一特性呢?可能项目B实现了两个特性,其中的特性一依赖于X,特性二依赖于Y,而且这两个特性是互斥的,用户不可能同时使用两个特性。比如B是一个持久层隔离工具包,它支持多种数据库,报错MySQL、Oracle,在构建这个工具包的时候,需要这两种数据库的驱动程序,但是在使用这个工具包的时候,只会依赖一种数据库。
下面为项目B的可选依赖的配置
&modelVersion&3.0.0&/modelVersion&
&groupId&com.up366.feishu&/groupId&
&artifactId&project-B&/artifactId&
&version&1.0.0&/version&
&dependencies&
&dependency&
&groupId&mysql&/gruopId&
&artifactId&mysql-connector-java&/artifact&
&version&5.1.10&/version&
&optional&true&/optional&
&/dependency&
&groupId&oracle&/gruopId&
&artifactId&oracle-connector-java&/artifact&
&version&6.1.15&/version&
&optional&true&/optional&
&/dependency&
&/dependencies&
&/project&
上述XML代码片段中,使用
&modelVersion&3.0.0&/modelVersion&
&groupId&com.up366.feishu&/groupId&
&artifactId&project-A&/artifactId&
&version&1.0.0&/version&
&dependencies&
&dependency&
&groupId&mysql&/gruopId&
&artifactId&mysql-connector-java&/artifact&
&version&5.1.10&/version&
&/dependency&
&/dependencies&
&/project&
在理想的情况下,是不应该使用可选依赖的。除非是某一个项目实现了多个互斥的特性,在面向对象设计中,有个单一职责性原则,意指一个类应该只要一项职责。
8、排除依赖
传递性依赖会给项目隐式地引入很多依赖,这极大的简化了项目依赖的管理,但是有时候这种特性也会带来问题。例如,当前项目有一个第三方依赖,而这个第三方依赖由于某些原因依赖了另外一个类库的SNAPSHOT版本,那么这个SNAPSHOT就会成为当前项目的传递性依赖,而SNAPSHOT版本的不稳定性会直接影响到当前的项目,这时就需要排除掉SNAPSHOT,并且在当前项目中声明该类库的某个正式发布的版本,排除传递性依赖的代码如下:
&groupId&com.up366.feishu&/groupId&
&artifactId&project-A&/artifactId&
&version&1.0.0&/version&
&dependencies&
&dependency&
&groupId&com.up366.feishu&/groupId&
&artifactId&project-B&/artifactId&
&version&1.0.0&/version&
&exclusions&
&exclusion&
&groupId&com.up366.feishu&/groupId&
&artifactId&project-C&/artfactId&
&/exclusion&
&/exclusions&
&/dependency&
&dependency&
&groupId&com.up366.feishu&/groupId&
&artifactId&project-C&/artifactId&
&version&1.1.0&/version&
&/dependency&
&/dependencies&
上面代码中,项目A依赖于项目B,但是由于一些原因,不想引入传递性依赖C,而是在自己显式的声明对于项目C1.1.0版本的依赖。代码中使用exclusion元素声明排除依赖,exclusions可以包含一个或者多个exclusion子元素,因此可以排除一个或者多个传递性依赖。
需要声明的是,声明exclusion的时候只需要groupId和artifactId而不需要version元素。这是因为只需要groupId和artifactId就能唯一定位依赖图中的某个依赖。
9、归并依赖
举个例子,Spring Framework包含很多模块,例如core:2.5.6、bean:2.5.6、context:2.5.6和support:2.5.6,他们来着同一项目的不同模块,因此,所有这些依赖的版本都是相同的,而且,如果以后需要升级Spring Framework,这些依赖的版本会一起升级,这样我们就可以像Java中声明一个Constants一样,为依赖的项目的版本设置一个这样类似常量的东西。这样在升级Spring Framework的时候就需要修改一处,代码如下:
&modelVersion&4.0.0&/modelVersion&
&groupId&com.up366.feishu&/groupId&
&artfactId&feishu_v3&/artifactId&
&name&feishu_v3&/name&
&version&1.0.0-SNAPSHOT&/version&
&properties&
&springframework.version&2.5.6&/springframework.version&
&/properties&
&dependencies&
&dependency&
&groupId&org.springframework&/groupId&
&artifact&spring-core&/artifact&
&version&${springframework.version}&/version&
&/dependency&
&dependency&
&groupId&org.springframework&/groupId&
&artifact&spring-beans&/artifact&
&version&${springframework.version}&/version&
&/dependency&
&dependency&
&groupId&org.springframework&/groupId&
&artifact&spring-context&/artifact&
&version&${springframework.version}&/version&
&/dependency&
&dependency&
&groupId&org.springframework&/groupId&
&artifact&spring-context-support&/artifact&
&version&${springframework.version}&/version&
&/dependency&
&/dependencies&
&/project&
上面首先使用了properties元素定义Maven属性,该例中定义了一个springframework.version子元素,其值为2.5.6.有了这个属性定义之后,Maven运行的时候会将POM中的${springframework.version}替换成值2.5.6。也就是说,可以使用美元符号和大括弧环绕的方式引用Maven属性。然后将所有Spring Framework依赖的版本值用这一属性引用表示,这和Java中的常量是一样的道理,不同的只是语法。
10、优化依赖
查看已解析依赖
可以使用命令,以列表的形式查看已经解析的依赖,还可以查看这些依赖的范围,如下:
列表形式查看命令:mvn dependency:list
树状结构查看命令:mvn dependency:tree
依赖分析命令:mvn dependency:analyze
mvn dependency:analyze由两部分组成,首先是Used updeclared dependencies,意指项目中使用到的,没有显式声明的依赖。
其次是Unused declared dependencies,意指项目中没有使用的,但是显是声明了的依赖。需要注意的是,对于这一类依赖,我们不应该简单的直接删除其声明,而是应该仔细分析,由于dependency:analyze只会分析编译主代码和测试代码需要用到的依赖,一些执行测试和运行时需要的依赖它就发现不了。建议不要乱删,当然有时候确实能通过该信息找到一些没用的依赖,但一定要小心测试。
阅读(...) 评论()maven依赖范围和依赖传递
compile (编译范围)
compile是默认的范围;如果没有提供一个范围,那该依赖的范围就是编译范围。编译范围依赖在所有的classpath
中可用,同时它们也会被打包。
provided (已提供范围)
provided 依赖只有在当JDK
或者一个容器已提供该依赖之后才使用。例如,如果你开发了一个web
应用,你可能在编译 classpath
中需要可用的Servlet API
来编译一个servlet,但是你不会想要在打包好的WAR
中包含这个Servlet API;这个Servlet API JAR
由你的应用服务器或者servlet
容器提供。已提供范围的依赖在编译classpath
(不是运行时)可用。它们不是传递性的,也不会被打包。
runtime (运行时范围)
runtime 依赖在运行和测试系统的时候需要,但在编译的时候不需要。比如,你可能在编译的时候只需要JDBC API JAR,而只有在运行的时候才需要JDBC驱动实现。
test (测试范围)
test范围依赖在一般的编译和运行时都不需要,它们只有在测试编译和测试运行阶段可用。
system (系统范围)
system范围依赖与provided
类似,但是你必须显式的提供一个对于本地系统中JAR
文件的路径。这么做是为了允许基于本地对象编译,而这些对象是系统类库的一部分。这样的构件应该是一直可用的,Maven
也不会在仓库中去寻找它。如果你将一个依赖范围设置成系统范围,你必须同时提供一个 systemPath
元素。注意该范围是不推荐使用的(你应该一直尽量去从公共或定制的 Maven
仓库中引用依赖)。
最左边一行表示第一直接依赖范围,最上面一行表示第二直接依赖范围,中间的交叉单元格则表示传递性依赖范围。
仔细观察上面表格,我们发现这样的规律:
当第二直接依赖的范围是compile的时候,传递性依赖的范围与第一直接依赖的范围一致;当第二直接依赖的范围是test的时候,依赖不会得以传递;当第二直接依赖的范围是provided的时候,只传递第一直接依赖的范围也为provided的依赖,切传递性依赖的范围同样为provided;当第二直接依赖的范围是runtime的时候,传递性依赖的范围与第一直接依赖的范围一致,但compile例外,此时传递性依赖的范围为runtime。
[Maven实战](9)传递性依赖
Maven管理(依赖范围,依赖传递,依赖冲突,依赖可选,依赖排除)
Maven 依赖范围、依赖传递、排除依赖
maven的依赖传递性讲解
在Java中使用OpenCV (maven,ant,eclipse)
没有更多推荐了,

我要回帖

更多关于 maven多项目依赖 的文章

 

随机推荐