搜索 K
Appearance
博客正在加载中...
Appearance
本文介绍关于依赖管理的更多概念
当我们需要用到的依赖多之后,一般会使用一个统一的版本,此时我们可以的配置可能是这样的:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
</dependency> 例如本例是使用 5.0.2.RELEASE。此时我们可能遇到这样的问题:升级版本。那么我们需要将所有涉及到的版本都改一遍!而我们可以通过配置 properties 的方式来简化配置:
<properties>
<spring.version>5.0.2.RELEASE</spring.version>
</properties> 然后在用到的地方使用该 properties:这样就可以统一修改版本号了,其实这是 EL 表达式的一种。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency> Maven 自己会有一些内置属性:
${basedir} 项目根目录${project.build.directory} 构建目录,缺省为 target${project.build.outputDirectory} 构建过程输出目录,缺省为 target/classes${project.build.finalName} 产出物名称,缺省为 ${project.artifactId}-${project.version}${project.packaging} 打包类型,缺省为 jar${project.xxx} 当前 pom 文件的任意节点的内容 每个 Maven 项目,都需要定义自己本身的坐标,例如本项目在 pom.xml 文件有这样的定义:
<!--项目名称,定义为组织名+项目名,类似包名-->
<groupId>com.peterjxl.LearnJavaMaven</groupId>
<!-- 模块名称 -->
<artifactId>hello-world</artifactId>
<!-- 当前项目版本号,snapshot 为快照版本即非正式版本,release 为正式发布版本 -->
<version>0.0.1-SNAPSHOT</version>为什么项目也要定义坐标呢?因为项目本身也可以作为一个依赖,供其他项目使用!有很多开源项目,例如 Log4j 框架,其本身也是用 Maven 来管理的,也有引入其他依赖。
Maven 对依赖的分类:
添加依赖需要指定依赖 jar 包的坐标,但是很多情况我们是不知道 jar 包的的坐标,可以通过如下网址查询:
然后就可以选择复制 Maven 的坐标,或者下载 JAR 文件

A 依赖 B,需要在 A 的 pom.xml 文件中添加 B 的坐标, 添加坐标时需要指定依赖范围 <scope>,依赖范围包括:
| 依赖范围 | 对于编译 classpath 有效 | 对于测试 classpath 有效 | 对于运行时 classpath 有效 | 例子 |
|---|---|---|---|---|
| compile | Y | Y | Y | Spring-Core |
| test | - | Y | - | Junit |
| provided | Y | Y | - | Servlet-api |
| Runtime | - | Y | Y | JDBC 驱动 |
| |
有时候,一个开源项目 A,会依赖于另一个开源项目 B;
而我们引入开源项目 A 的时候,Maven 会将项目 A,需要的依赖,也引入进来。例如,当我们引入 Spring 框架的时候:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency> 可以看到 Spring 还依赖于不少依赖:
这样做有好处也有坏处:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
</dependencies>虽然 spring-context 已经包含了 spring-beans <,但我们现在是为了演示问题,所以特地添加的。
我们可以通过 IDEA 来查看项目的依赖情况:首先打开 Maven 的工具面板,然后点击右上角的查看依赖关系(或者快捷键 Ctrl + Shift + Alt + U)
我们可以看到,我们的项目的依赖情况,这里以一个网上的截图为例:
由下往上看,我们的项目,使用了两个依赖:
我们可以看看 IDEA 的视图,可以看到最后用的还是 spring-core 5.0.2 的版本:
但如果说我们将依赖的顺序调换下:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency> 此时,用的就是 4.2.4 的版本了!

因此我们引入依赖的时候,必须考虑如何解决。解决 jar 包冲突的方式:
方式一:第一声明优先原则。哪个 jar 包的坐标在靠上的位置,这个 jar 包就是先声明的。先声明的 jar 包坐标下的依赖包,可以优先进入项目中。
方式二:路径近者优先原则。直接依赖路径比传递依赖路径近,那么最终项目进入的 jar 包会是路径近的直接依赖包
方式三【推荐使用】:直接排除法。当我们要排除某个 jar 包下依赖包,配置 exclusions 标签。内部可以不写版本号,因为此时依赖包使用的版本和默认和本 jar 包一样,例如本例中就是 spring-beans 的版本 4.2.4。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.4.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
</exclusions>
</dependency>maven 工程是可以分父子依赖关系的。
凡是依赖别的项目后,拿到的别的项目的依赖包,都属于传递依赖。比如:当前 A 项目,被 B 项目依赖。那么我们 A 项目中所有 jar 包都会传递到 B 项目中。
B 项目开发者,如果再在 B 项目中导入一套 ssm 框架的 jar 包,对于 B 项目是直接依赖,那么直接依赖的 jar 包就会把我们 A 项目传递过去的 jar 包覆盖掉。
为了防止以上情况的出现。我们可以把 A 项目中主要 jar 包的坐标锁住,那么其他依赖该项目的项目中,即便是有同名 jar 包直接依赖,也无法覆盖。
配置方法:使用 <dependencyManagement> 标签
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
</dependencies>
</dependencyManagement> 注意,锁定的 jar 包仅仅是锁定作用,并没有引入依赖。
有时候我们知道类名,但是不知道对应的 Maven 依赖,也可以通过搜索来找到。
一. 已知全类名:输入 fc: org.apache.poi.xssf.usermodel.XSSFWorkbook (注:fc 代表 full class)
二. 已知类名:输入 c: 类名(注:c 代表 class)
三. 已知 Group ID 或者 Artifact ID,g: com.alibaba a: druid
我们讲了什么是依赖,并且介绍了 scope 和依赖冲突的方式,下一篇我们来讲讲插件管理。