繁琐的任务简单化,Maven依赖总结
有人认为Maven是一个依赖管理工具,当然这种想法是错误的(确切的说Maven是一个项目管理工具,贯穿了整个项目生命周期,编译,测试,打 包,发布...),但Maven给人造成这种错误的印象也是有原因的,因为Maven的依赖管理十分强大,用好了Maven,你不再需要面对一大堆jar 感到头大,依赖冲突,无用依赖等问题也能够得到有效的防止和解决。
一、依赖
依赖是Maven 中最关键的部分,我们之所以在工程中使用Maven,就是因为它的依赖管理功能。如果我们想要在工程中引入某个jar 包,只需要在pom.xml 中引入其jar 包的坐标即可。比如引入log4j 的依赖:
log4j
log4j
1.2.17
compile
groupId,必选,实际隶属项目
artifactId,必选,其中的模块
version必选,版本号
type可选,依赖类型,默认jar
scope可选,依赖范围,默认compile
optional可选,标记依赖是否可选,默认false
exclusion可选,排除传递依赖性,默认空
二.依赖范围
Maven 提供了六种依赖的范围:compile、test、provided、runtime、system 和import。其中compile 是默认的依赖范围。这里主要对比前三种常用的依赖范围。
maven项目有三种classpath(编译,测试,运行)
scope用来表示与classpath的关系,总共有五种
compile:编译,测试,运行
test:测试
provided:编译,测试
runtime:运行
system:编译,测试,同provided,但必须指定systemPath,慎用
三.传递性依赖
顾名思义,你懂的,但是传递的范围会发生改变,这个由maven自身处理,只要理解下即可
第一列为第一依赖,第二列为第二依赖,单元格为传递范围
compiletestprovidedruntime
compilecompile__runtime
testtest__test
providedprovided_providedprovided
runtimeruntime__runtime
四.依赖调解
传递路径长度取最短原则,传递路径长度相等时,采取最先申明原则
如果A 依赖于B,B 依赖于C,在B 和C 中同时有log4j 的依赖,并且这两个版本不一致,那么A 会根据最短路径原则,在A 中会传递过来B 的log4j版本
如果在A 同时依赖于B 和C,B 和C 没有依赖关系,并且都有log4j 的依赖,且版本不一致,那么A 会引入在pom.xml 中先声明依赖的log4j 版本
五.可选依赖
尽量少用,可选依赖不会被传递,需要显式申明。例如下例,B有一个持久层工具包依赖,他依赖了两种数据库驱动,这两种特性只需要选择一种,这种传递性依赖是不会给传递的,需要在A项目中另外依赖数据库驱动依赖。
mysql
mysql-connector-java
5.1.10
true
postgresql
postgresql
8.4.701.jdbc3
true
正常情况不应该使用可选依赖,可选依赖一般是项目有多个特性,在面向对象设计中单一原则意指一个类应该只有一项职责。
六.排除依赖
发现依赖包里有些包不稳定,可以排除依赖,显式的申明文档的包。
javax.mail
1.4.1
javax.activation
activation
javax.activation
activation
1.1
七.分类依赖
当同一个模块,所依赖的几个模块版本都相同时,可以使用maven里的属性做分类依赖,依赖版本升级时改一处即可
2.5.6
org.springframework
spring-core
${springframework.version}
jar
compile
org.springframework
spring-beans
${springframework.version}
pom
compile
org.springframework
spring-context
${springframework.version}
jar
compile
org.springframework
spring-context-support
${springframework.version}
jar
compile
八.优化依赖
可概括为三个命令
mvn dependency:list
表示依赖列表,maven eclipse插件已经实现,有图形化显示,在pom.xml的dependencies页
mvn dependency:tree
表示依赖树,maven eclipse插件已经实现,有图形化显示,在pom.xml的dependency hierarchy页
mvn dependency:analyze
表示依赖分析,命令可以分析当前依赖,包括哪些依赖被import却没引入,哪些引来引入了但是没加入编译。有时候可以用来删除一些没用的依赖,但是不能直接删除,比如sprint-core是Spring的必须依赖,但是会提示没加入编译,但是他又是Spring框架必须的。