Maven讲解之 依赖管理
本章节我们将通过两个例子来实例讲解一下Maven的依赖关系。
两个例子
新建两个Maven Project(War)。一客户模块和市场模块作为例子(只举业务逻辑例子,无核心代码)。另外Customer Model 将依赖于Market Model。
- Market Model
- 目录结构
- 操作点
- install(install 该项目,使Maven 初次下载其生命周期管理的组件)
右键项目->Run as ->Maven install
- compile(编译该项目形成Market的SNAPSHOT jar(编译后的class文件))
右键项目->Run as ->Maven build….. ->goals:compile
- pom.xml
- 4.0.0
- com.sspts.oscar
- Market
- 0.0.1-SNAPSHOT
- war
Customer Model
目录结构
操作点
• 统一管理jar包版本
1.
2. UTF-8
3. 4.0.4.RELEASE
4.
• 引用其他模块的jar包
5.
6. com.sspts.oscar
7. Market
8. 0.0.1-SNAPSHOT
9. compiler
10.
• 去掉对Spring core jar 包中对commons-logging的依赖
11.
12.
13. commons-logging
14. commons-logging
15.
16.
• pom.xml
17.
18. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
19. 4.0.0
20. com.sspts.oscar
21. Customer
22. 0.0.1-SNAPSHOT
23. war
24.
25. UTF-8
26. 4.0.4.RELEASE
27.
28.
29.
30.
31. org.springframework
32. spring-aop
33. ${spring.version}
34.
35.
36. commons-logging
37. commons-logging
38.
39.
40.
41.
42. org.springframework
43. spring-aspects
44. ${spring.version}
45.
46.
47. org.springframework
48. spring-beans
49. ${spring.version}
50.
51.
52. org.springframework
53. spring-context
54. ${spring.version}
55.
56.
57.
58. com.sspts.oscar
59. Market
60. 0.0.1-SNAPSHOT
61. compiler
62.
63.
64.
65. javax.servlet
66. javax.servlet-api
67. 3.1.0
68. provided
69.
70.
注:本例子只引用了Spring 的部分jar包,请结合实际需求引用spring的jar包。
实例讲解
Maven 中最关键的部分,我们使用 Maven 最主要的就是使用它的依赖管理功能。要理解和掌握 Maven 的依赖管理,我们只需要解决一下几个问题:
- 依赖的目的是什么
当 A jar 包用到了 B jar 包中的某些类时,A 就对 B 产生了依赖,这是概念上的描述。那么如何在项目中以依赖的方式引入一个我们需要的 jar 包呢?
答案非常简单,就是使用 dependency 标签指定被依赖 jar 包的坐标就可以了。如本章例子,Customer Model 引用到了Market Model 的SNAPSHOT
- com.sspts.oscar
- Market
- 0.0.1-SNAPSHOT
- compiler
- 依赖的范围
大家注意到上面的依赖信息中除了目标 jar 包的坐标还有一个 scope 设置,这是依赖的范围。依赖的范围有几个可选值,我们用得到的是:compile、test、provided 三个。
- [1]从项目结构角度理解 compile 和 test 的区别
从上面的依赖关系可以看出不论是主程序(main下面的JAVA文件)还是测试程序(test下面的JAVA文件)都使用到了compile依赖,而test依赖只用于测试程序。
- [2]从开发和运行这两个不同阶段理解 compile 和 provided 的区别
正如我们在Customer Model pom.xml中对 Servlet API的依赖范围定义所示,将Servlet API的依赖范围定义为provided,即在开发阶段我们会依赖Servlt API,一旦项目部署以后,项目将直接忽略Servlet API,二运行阶段酱油Servlet容器提供Servlet API。
- [3]有效性总结
- 依赖的传递性
A 依赖 B,B 依赖 C,A 能否使用 C 呢?那要看 B 依赖 C 的范围是不是 compile,如果是则可用,否则不可用。
- 依赖的排除
如果我们在当前工程中引入了一个依赖是 A,而 A 又依赖了 B,那么 Maven 会自动将 A 依赖的 B 引入当前工程,但是个别情况下 B 有可能是一个不稳定版,或对当前工程有不良影响。这时我们可以在引入 A 的时候将 B 排除。
- 情景举例
不排除依赖时
- org.springframework
- spring-aop
- ${spring.version}
- 排除依赖时
1.
2. org.springframework
3. spring-aop
4. ${spring.version}
5.
6.
7. commons-logging
8. commons-logging
9.
10.
11.
• 统一管理所依赖 jar 包的版本
对同一个框架的一组 jar 包最好使用相同的版本。为了方便升级框架,可以将 jar 包的版本信息统一提取出来。例如在Customer Model中我们在pom.xml对spring 以及sourceEncoding做了版本和格式的限制。
• 统一声明版本号
1.
2. UTF-8
3. 4.0.4.RELEASE
4.
• 引用前面声明的版本号
5.
6. org.springframework
7. spring-aspects
8. ${spring.version}
9.
• 依赖的原则:解决 jar 包冲突
路径最短者优先
路径相同时先声明者优先
这里“声明”的先后顺序指的是 dependency 标签配置的先后顺序。